zoukankan      html  css  js  c++  java
  • 定位服务API案例

    定位服务API案例

    要使用定位服务API,需要确保设备已经下载并安装了HMS Core服务组件,并将Location Kit的SDK集成到项目中。

    指定应用权限

    1. Android提供了两种位置权限: ACCESS_COARSE_LOCATION(粗略的位置权限)和ACCESS_FINE_LOCATION(精确的位置权限)。需要在“AndroidManifest.xml”文件中申请权限:
    2. <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    3. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    4. 在Android Q版本中,如果需要应用程序在后台执行时也具备持续定位能力,需要在“AndroidManifest.xml”文件中申请ACCESS_BACKGROUND_LOCATION权限:
    5. <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    6. 在“AndroidManifest.xml”中添加后,还要在代码中动态申请一下权限(Android 6.0危险权限要求):
    7. // Android SDK<=28 所需权限动态申请
    8. if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
    9.     Log.i(TAG, "android sdk <= 28 Q");
    10.     if (ActivityCompat.checkSelfPermission(this,
    11.         Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
    12.         && ActivityCompat.checkSelfPermission(this,
    13.             Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    14.         String[] strings =
    15.             {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
    16. 10.         ActivityCompat.requestPermissions(this, strings, 1);
    17. 11.     }

    12. } else {

    1. 13.     // Android SDK>28 所需权限动态申请,需添加“android.permission.ACCESS_BACKGROUND_LOCATION”权限
    2. 14.     if (ActivityCompat.checkSelfPermission(this,
    3. 15.         Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
    4. 16.         && ActivityCompat.checkSelfPermission(this,
    5. 17.             Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
    6. 18.         && ActivityCompat.checkSelfPermission(this,
    7. 19.             "android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
    8. 20.         String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION,
    9. 21.             android.Manifest.permission.ACCESS_COARSE_LOCATION,
    10. 22.             "android.permission.ACCESS_BACKGROUND_LOCATION"};
    11. 23.         ActivityCompat.requestPermissions(this, strings, 2);
    12. 24.     }

    25. }

    创建定位服务客户端

    在项目中使用到定位服务的Activity中的onCreate()方法中创建一个FusedLocationProviderClient实例,通过该实例调用定位相关接口。

    1. // 定位交互接入对象
    2. private FusedLocationProviderClient fusedLocationProviderClient;
    3. // 定位请求信息对象
    4. private LocationRequest mLocationRequest;       
    5. protected void onCreate(Bundle savedInstanceState) {  
    6.     fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
    7. }

    说明

    当传入参数为非Activity类型时,如果使用FusedLocationProviderClient实例调用定位服务接口发生异常,就不会弹出UI交互界面提示用户处理,只会返回错误码。例如:当HMS Core不符合定位服务的版本要求时,便会返回错误码907135003,此时需要手动升级HMS Core。如果需要拉起升级引导界面,建议传入Activity类型参数替代Context类型,创建FusedLocationProviderClient实例。

    检查设备定位设置

    设备的相关定位设置会影响定位服务的定位结果,例如位置开关选项处于关闭状态时,将无法获取到位置信息。因此,建议在持续获取位置信息之前,先检查设备设置是否满足定位条件。定位服务提供了检查设备定位相关设置的能力,通过LocationServicesgetSettingsClient(Activity activity)获取SettingsClient实例,然后调用checkLocationSettings(LocationSettingsRequest locationSettingsRequest)接口获取定位设置结果,当设置不满足定位条件时,可以调用startResolutionForResult接口用于弹框提示用户打开对应的权限(HMS Core 定位权限必须打开,Android Q版本必须选择“始终允许”)。

    1. 调用getSettingsClient()接口获取SettingsClient实例。
    2. SettingsClient settingsClient = LocationServices.getSettingsClient(this);
    3. 调用checkLocationSettings()检查设备设置。
    4. LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
    5. mLocationRequest = new LocationRequest();
    6. builder.addLocationRequest(mLocationRequest);
    7. LocationSettingsRequest locationSettingsRequest = builder.build();
    8. // 检查设备定位设置
    9. settingsClient.checkLocationSettings(locationSettingsRequest)
    10.     // 检查设备定位设置接口成功监听回调
    11.     .addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
    12.         @Override
    13. 10.         public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
    14. 11.             // 设置满足定位条件,再发起位置请求
    15. 12.             fusedLocationProviderClient
    16. 13.                 .requestLocationUpdates(mLocationRequest, mLocationCallback,Looper.getMainLooper())
    17. 14.                 // 请求位置更新接口成功监听回调
    18. 15.                 .addOnSuccessListener(new OnSuccessListener<Void>() {
    19. 16.                     @Override
    20. 17.                     public void onSuccess(Void aVoid) {
    21. 18.                         // ...
    22. 19.                     }
    23. 20.                 });
    24. 21.         }
    25. 22.     })
    26. 23.     // 检查设备定位设置接口失败监听回调
    27. 24.     .addOnFailureListener(new OnFailureListener() {
    28. 25.         @Override
    29. 26.         public void onFailure(Exception e) {
    30. 27.             // 设置不满足定位条件
    31. 28.             int statusCode = ((ApiException) e).getStatusCode();
    32. 29.             switch (statusCode) {
    33. 30.                 case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
    34. 31.                     try {
    35. 32.                         ResolvableApiException rae = (ResolvableApiException) e;
    36. 33.                         // 调用startResolutionForResult可以弹窗提示用户打开相应权限
    37. 34.                         rae.startResolutionForResult(MainActivity.this, 0);
    38. 35.                     } catch (IntentSender.SendIntentException sie) {
    39. 36.                         // …
    40. 37.                     }
    41. 38.                 break;
    42. 39.             }
    43. 40.         }
    44. 41.     });

    持续获取位置信息

    如果希望应用可以持续获取设备位置,可以使用定位服务提供的requestLocationUpdates()接口。该接口根据入参形式的不同,将以两种不同的形式将位置信息返回。一种是通过调用已经定义的LocationCallback类中onLocationResult()回调方法返回一个包含位置信息的LocationResult对象,另一种是将位置信息置于PendingIntent扩展信息中返回。

    当应用程序不再需要接收位置更新时,应当停止位置更新,以便于降低功耗。要停止位置更新,可以调用removeLocationUpdates(),传入与requestLocationUpdates()接口相对应的LocationCallback或PendingIntent对象。这里以回调方式作为样例,代码如下。详细的参数说明请参见LocationService接口说明。

    1. 设置持续定位请求参数。
    2. LocationRequest mLocationRequest = new LocationRequest();
    3. // 设置位置更新的间隔(单位为毫秒)
    4. mLocationRequest.setInterval(10000);
    5. // 设置定位类型
    6. mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    7. 定义位置更新回调。
    8. LocationCallback mLocationCallback;       
    9. mLocationCallback = new LocationCallback() {       
    10.     @Override       
    11.     public void onLocationResult(LocationResult locationResult) {       
    12.         if (locationResult != null) {       
    13.             // 处理位置回调结果
    14.         }       
    15.     }       
    16. };
    17. 调用requestLocationUpdates()进行持续定位。
    18. fusedLocationProviderClient       
    19.     .requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper())       
    20.     .addOnSuccessListener(new OnSuccessListener<Void>() {       
    21.         @Override       
    22.         public void onSuccess(Void aVoid) {       
    23.             // 接口调用成功的处理
    24.         }       
    25.     })
    26.     .addOnFailureListener(new OnFailureListener() {       
    27. 10.         @Override       
    28. 11.         public void onFailure(Exception e) {       
    29. 12.            // 接口调用失败的处理
    30. 13.         }       
    31. 14.     });

    说明

    如果接口调用成功,获取位置信息失败,请参见接口调用成功,获取不到位置信息

    1. 调用removeLocationUpdates()停止位置更新。
    2. // 注意:停止位置更新时,mLocationCallback必须与requestLocationUpdates方法中的LocationCallback参数为同一对象。
    3. fusedLocationProviderClient.removeLocationUpdates(mLocationCallback)       
    4.     // 停止位置更新成功监听回调
    5.     .addOnSuccessListener(new OnSuccessListener<Void>() {       
    6.         @Override       
    7.         public void onSuccess(Void aVoid) {     
    8.            //...
    9.         }       
    10.     })
    11. 10.     // 停止位置更新失败监听回调
    12. 11.     .addOnFailureListener(new OnFailureListener() {       
    13. 12.         @Override       
    14. 13.         public void onFailure(Exception e) {     
    15. 14.            // ...
    16. 15.         }       
    17. 16.     });

    获取最后的已知位置

    应用可以调用getLastLocation()方法获取设备最后的已知位置,大多情况下,该位置即为设备的当前位置。代码样例如下:

    1. // 获取最后的已知位置
    2. Task<Location> task = fusedLocationProviderClient.getLastLocation()       
    3.     // 获取最后的已知位置成功监听回调
    4.     .addOnSuccessListener(new OnSuccessListener<Location>() {       
    5.         @Override     
    6.         public void onSuccess(Location location) {       
    7.             if (location == null) {       
    8.                return;       
    9.             }       
    10. 10.             // 成功时Location对象处理逻辑
    11. 11.             // ...
    12. 12.         }       
    13. 13.     })
    14. 14.     // 获取最后的已知位置失败监听回调
    15. 15.     .addOnFailureListener(new OnFailureListener() {       
    16. 16.         @Override       
    17. 17.         public void onFailure(Exception e) {       
    18. 18.            // ...
    19. 19.         }       
    20. 20.     });

    说明

    getLastLocation()方法是从系统缓存中获取位置信息的。如果获取的位置信息为null,则可能是系统缓存已经被清除;此时先调用requestLocationUpdates()方法获取位置信息以刷新缓存,再调用getLastLocation()方法即可以获取到位置信息。

    使用模拟位置信息功能

    具体操作步骤:打开“设置 > 系统和更新 > 开发人员选项 > 选择模拟位置信息应用 > 选择要模拟位置信息应用”(如果没有发现“开发人员选项”,请执行如下操作:“设置 > 关于手机 > 版本号”,连续点击“版本号”7次,“开发人员选项”会出现在“系统与更新”页面,再重复上述操作),代码开发步骤如下:

    1. 在AndroidManifest.xml文件中配置模拟定位权限。
    2. <uses-permission
    3. android:name="android.permission.ACCESS_MOCK_LOCATION"
    4. tools:ignore="MockLocation,ProtectedPermissions" />
    5. 设置mock模式,调用setMockMode(boolean isMockMode)。
    6. // 设置mock模式,参数传入ture:模拟模式;false:正常状态
    7. boolean mockFlag = true;
    8. fusedLocationProviderClient.setMockMode(mockFlag)
    9.     .addOnSuccessListener(new OnSuccessListener<Void>() {
    10.         @Override
    11.         public void onSuccess(Void aVoid) {
    12.             Log.i(TAG, "setMockMode onSuccess");
    13.         }
    14.     })
    15. 10.     .addOnFailureListener(new OnFailureListener() {
    16. 11.         @Override
    17. 12.         public void onFailure(Exception e) {
    18. 13.             Log.i(TAG, "setMockMode onFailure:" + e.getMessage());
    19. 14.         }
    20. 15.     });
    21. 设置模拟位置信息,调用setMockLocation(Location mockLocation)。
    22. // 设置模拟位置信息
    23. final Location mockLocation = new Location(LocationManager.GPS_PROVIDER);
    24. mockLocation.setLongitude(118.76);
    25. mockLocation.setLatitude(31.98);
    26. fusedLocationProviderClient.setMockLocation(mockLocation)
    27.     // 设置模拟位置信息成功监听回调
    28.     .addOnSuccessListener(new OnSuccessListener<Void>() {
    29.         @Override
    30.         public void onSuccess(Void aVoid) {
    31. 10.             Log.i(TAG, "setMockLocation onSuccess");
    32. 11.         }
    33. 12.     })
    34. 13.     // 设置模拟位置信息失败监听回调
    35. 14.     .addOnFailureListener(new OnFailureListener() {
    36. 15.         @Override
    37. 16.         public void onFailure(Exception e) {
    38. 17.             Log.i(TAG, "setMockLocation onFailure:" + e.getMessage());
    39. 18.         }
    40. 19.     });
    人工智能芯片与自动驾驶
  • 相关阅读:
    转:testlink 环境搭建(傻瓜版)
    转最简便安装python+selenium-webdriver环境方法
    转发 python中file和open有什么区别
    一面cvte
    org.apache.hadoop.security.AccessControlException: Permission denied:
    让hadoop-0.20.2自带的eclipse插件支持eclipse-3.5以上
    在VMWare中建立Hadoop虚拟集群的详细步骤(使用CentOS)
    第一天
    执行insmod提示invalidmodule format
    Linux Kernel中函数命名
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/14342869.html
Copyright © 2011-2022 走看看