美文网首页
在Android中获取用户位置

在Android中获取用户位置

作者: 小城哇哇 | 来源:发表于2022-10-16 17:45 被阅读0次

    获取用户在Android中的位置可以通过以下步骤完成:

    1. 在渐变中添加依赖关系

    在生成.gradle(应用)文件中添加以下依赖项:

    dependencies {
        implementation 'com.google.android.gms:play-services-location:19.0.0'
    }
    
    

    获取用户权限

    可以使用以下任何权限:
    (在 Android 清单中添加这些权限.xml文件)

    ACCESS_COARSE_LOCATION:它提供城市街区内的位置精度

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    
    

    ACCESS_FINE_LOCATION:它提供了更准确的位置

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
    

    ACCESS_BACKGROUND_LOCATION:如果应用需要在后台运行时访问用户的位置,我们需要将此权限与上述权限一起添加

    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    
    

    📌 准确性

    安卓系统支持以下级别的定位精度:

    近似
    提供设备位置的估计值,在大约1.6 公里内。当您声明ACCESS_COARSE_LOCATION权限而不是ACCESS_FINE_LOCATION权限时,您的应用将使用此级别的位置准确性。

    精确
    提供尽可能准确的设备位置估计值,通常在大约 160 英尺(50 米)以内,有时精确到 10 英尺(几米)或更好。你的应用在声明ACCESS_FINE_LOCATION权限时使用此级别的位置准确性。

    注意:

    在 Android 12(API 级别 31)或更高版本上,用户可以请求您的应用仅检索大致的位置信息,即使您的应用请求ACCESS_FINE_LOCATION运行时权限也是如此。

    若要处理此潜在用户行为,请不要自行请求ACCESS_FINE_LOCATION权限。相反,请在单个运行时请求中同时请求ACCESS_FINE_LOCATION权限和ACCESS_COARSE_LOCATION权限。如果您尝试仅请求ACCESS_FINE_LOCATION,系统将忽略某些版本的 Android 12 上的请求。

    如果您的应用以 Android 12 或更高版本为目标平台,系统会在 Logcat 中记录以下错误消息:

    ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION
    
    

    当你的应用同时请求ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION时,系统权限对话框将包含以下用户选项:

    精确:这允许你的应用获取精确的位置信息。
    近似值:这允许你的应用仅获取近似位置信息。

    设计布局

    创建文本视图以在屏幕上显示用户的纬度和经度

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Location here"
            android:textSize="24sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    

    逻辑

    我们将逻辑写入主活动文件中。在我的情况下,它是主要活动.java。

    创建一些基本变量:
    位置对象以存储用户的位置,
    FusedLocationProvider客户端对象以获取位置,整数请求代码用于权限,TextView对象用于向用户显示提取的位置

    还创建了一个用于获取位置的提取位置函数。

    它实际上是一种位置服务,结合了GPS定位和网络定位,以实现电池消耗和准确性之间的平衡。GPS 位置用于提供精度,网络位置用于在用户处于室内时获取位置。

    public class MainActivity extends AppCompatActivity {
        Location currentLocation;
        FusedLocationProviderClient fusedLocationProviderClient;
        private static final int REQUEST_CODE = 101;
        TextView textView;
    
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            textView = findViewById(R.id.textView);
    
            fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
            fetchLocation();
        }
    }
    
    

    所需的权限包括:

    • Manifest.permission.ACCESS_COARSE_LOCATION
    • Manifest.permission.ACCESS_FINE_LOCATION
    String[] LocationPermissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
                                            Manifest.permission.ACCESS_FINE_LOCATION};
    
    

    提取位置的逻辑可以如下:

    1. 检查我们请求的权限是否已启用。
    2. 如果未启用,请请求权限。
    3. 如果接受权限并启用位置,请获取用户的最后一个位置
    @RequiresApi(api = Build.VERSION_CODES.N)
    private void fetchLocation() {
            // Check for permissions
            if (ActivityCompat.checkSelfPermission
                    (this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // Request for permissions
                ActivityCompat.requestPermissions(
                        this, LocationPermissions, REQUEST_CODE);
                return;
            } else if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)) {
                Toast.makeText(this, "Location cannot be determined", Toast.LENGTH_SHORT).show();
                // Request for permissions
                ActivityCompat.requestPermissions(
                        this, LocationPermissions, REQUEST_CODE);
            }
    
            // Getting last location from Fused Location Provider Client Object
            fusedLocationProviderClient.getLastLocation().
                    addOnCompleteListener(new OnCompleteListener<Location>() {
                        @Override
                        public void onComplete(@NonNull Task<Location> task) {
                            Location location = task.getResult();
                            if (location == null) {
                                requestNewLocationData();
                            } else {
                                currentLocation = location;
                                textView.setText("Latitude:"+currentLocation.getLatitude()+"\nLongitude:"+currentLocation.getLongitude());
                            }
                        }
                    });
     }
    
    

    OnRequest权限结果 :

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if (requestCode == REQUEST_CODE) {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    fetchLocation();
                }
                else {
                    // Permission not granted
                    Toast.makeText(this, "Location cannot be determined", Toast.LENGTH_SHORT).show();
                    currentLocation=null;
                }
            }
     }
    
    

    正如在上面的 fetchLocation 方法中看到的,如果由 fused 位置获取的位置提供者客户端.getLastLocation() 为空,我们请求新的位置数据,从而创建一个名为 requestNewLocationData() 的方法

    fusedLocationProviderClient.getLastLocation().
            addOnCompleteListener(new OnCompleteListener<Location>() {
                @Override
                public void onComplete(@NonNull Task<Location> task) {
                    Location location = task.getResult();
                    if (location == null) {
                        requestNewLocationData(); // Here
                    } else {
                       // .....
                    }
                }
    
    

    RequestNewLocationData()

    现在将请求新的位置数据方法。

    🚩 创建类位置回调的变量(用于在设备位置已更改或无法再确定时从融合位置提供程序Api接收通知)

    private LocationCallback locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                Location location=locationResult.getLastLocation();
                currentLocation=location;
            }
        };
    
    

    🚩 创建新的位置请求变量。在此对象上,设置各种方法,例如设置位置的精度或要发出的位置请求的间隔数的优先级。

    🚩如果需要非常高的准确性,请使用PRIORITY_HIGH_ACCURACY作为 setPriority(int) 方法的参数。对于城市级精度(低精度),请使用PRIORITY_LOW_POWER。

    🚩位置请求对象准备就绪后,将其设置在融合位置提供程序客户端对象上以获取最终位置

    private void requestNewLocationData() {
            // Initializing LocationRequest object with appropriate methods
            LocationRequest locationRequest = new LocationRequest();
    
            //  For a city level accuracy(low accuracy), use PRIORITY_LOW_POWER.
            locationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
    
            // Set the desired interval for active location updates, in milliseconds.
            locationRequest.setInterval(5);
    
            // Explicitly set the fastest interval for location updates, in milliseconds
            locationRequest.setFastestInterval(0);
    
            // Set the number of location updates.
            locationRequest.setNumUpdates(1);
    
            // setting LocationRequest on FusedLocationClient
            fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
    
            // Check for permissions
            if (ActivityCompat.checkSelfPermission
                    (this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // Request for permissions
                ActivityCompat.requestPermissions(
                        this, LocationPermissions, REQUEST_CODE);
                return;
            } else if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)) {
                Toast.makeText(this, "Location cannot be determined", Toast.LENGTH_SHORT).show();
                // Request for permissions
                ActivityCompat.requestPermissions(
                        this, LocationPermissions, REQUEST_CODE);
            }
    
            fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
    }
    

    现在,你已成功获取用户的位置,并且可以根据需要在应用中实现此位置。

    完整代码

    完整的主要活动:

    package com.example.locationdemo;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.RequiresApi;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    
    import android.Manifest;
    import android.content.pm.PackageManager;
    import android.location.Location;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Looper;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.google.android.gms.location.FusedLocationProviderClient;
    import com.google.android.gms.location.LocationCallback;
    import com.google.android.gms.location.LocationRequest;
    import com.google.android.gms.location.LocationResult;
    import com.google.android.gms.location.LocationServices;
    import com.google.android.gms.tasks.OnCompleteListener;
    import com.google.android.gms.tasks.Task;
    
    public class MainActivity extends AppCompatActivity {
        Location currentLocation;
        FusedLocationProviderClient fusedLocationProviderClient;
        private static final int REQUEST_CODE = 101;
        TextView textView;
    
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            textView = findViewById(R.id.textView);
    
            fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
            fetchLocation();
        }
    
        String[] LocationPermissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
                                            Manifest.permission.ACCESS_FINE_LOCATION};
    
        @RequiresApi(api = Build.VERSION_CODES.N)
        private void fetchLocation() {
            // Check for permissions
            if (ActivityCompat.checkSelfPermission
                    (this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // Request for permissions
                ActivityCompat.requestPermissions(
                        this, LocationPermissions, REQUEST_CODE);
                return;
            } else if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)) {
                Toast.makeText(this, "Location cannot be determined", Toast.LENGTH_SHORT).show();
                // Request for permissions
                ActivityCompat.requestPermissions(
                        this, LocationPermissions, REQUEST_CODE);
            }
    
            // Getting last location from Fused Location Provider Client Object
            fusedLocationProviderClient.getLastLocation().
                    addOnCompleteListener(new OnCompleteListener<Location>() {
                        @Override
                        public void onComplete(@NonNull Task<Location> task) {
                            Location location = task.getResult();
                            if (location == null) {
                                requestNewLocationData();
                            } else {
                                currentLocation = location;
                                textView.setText("Latitude:"+currentLocation.getLatitude()+"\nLongitude:"+currentLocation.getLongitude());
                            }
                        }
                    });
        }
    
        private LocationCallback locationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                Location location=locationResult.getLastLocation();
                currentLocation=location;
            }
        };
    
        private void requestNewLocationData() {
            // Initializing LocationRequest object with appropriate methods
            LocationRequest locationRequest = new LocationRequest();
    
            //  For a city level accuracy(low accuracy), use PRIORITY_LOW_POWER.
            locationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
    
            // Set the desired interval for active location updates, in milliseconds.
            locationRequest.setInterval(5);
    
            // Explicitly set the fastest interval for location updates, in milliseconds
            locationRequest.setFastestInterval(0);
    
            // Set the number of location updates.
            locationRequest.setNumUpdates(1);
    
            // setting LocationRequest on FusedLocationClient
            fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
    
            // Check for permissions
            if (ActivityCompat.checkSelfPermission
                    (this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                // Request for permissions
                ActivityCompat.requestPermissions(
                        this, LocationPermissions, REQUEST_CODE);
                return;
            } else if (ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.ACCESS_FINE_LOCATION)) {
                Toast.makeText(this, "Location cannot be determined", Toast.LENGTH_SHORT).show();
                // Request for permissions
                ActivityCompat.requestPermissions(
                        this, LocationPermissions, REQUEST_CODE);
            }
    
            fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
        }
    
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if (requestCode == REQUEST_CODE) {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    fetchLocation();
                }
                else {
                    // Permission not granted
                    Toast.makeText(this, "Location cannot be determined", Toast.LENGTH_SHORT).show();
                    currentLocation=null;
                }
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:在Android中获取用户位置

          本文链接:https://www.haomeiwen.com/subject/iksdzrtx.html