定位服务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.     });

定位服务API案例的更多相关文章

  1. 【Android】18.2 利用百度定位服务API实现位置跟踪

    分类:C#.Android.VS2015: 创建日期:2016-03-04 一.简介 第3章已经介绍过百度定位SDK,这里再演示一遍其基本用法. 二.示例2-百度定位服务基本用法 运行截图 设计步骤 ...

  2. iOS6定位服务编程详解

    现在的移动设备很多都提供定位服务,使用iOS系统的iPhone.iPod Touch和iPad都可以提供位置服务,iOS设备能提供3种不同途径进行定位:Wifi, 蜂窝式移动电话基站, GPS卫星 i ...

  3. iOS定位服务编程详解

    现在的移动设备很多都提供定位服务,使用iOS系统的iPhone.iPod Touch和iPad都可以提供位置服务,iOS设备能提供3种不同途径进行定位:Wifi, 蜂窝式移动电话基站, GPS卫星 i ...

  4. 【Android】18.1 利用安卓内置的定位服务实现位置跟踪

    分类:C#.Android.VS2015: 创建日期:2016-03-04 一.安卓内置的定位服务简介 通常将各种不同的定位技术称为位置服务或定位服务.这种服务是通过电信运营商的无线电通信网络(如GS ...

  5. 【iOS】7.4 定位服务->2.1.4 定位 - 官方框架CoreLocation 案例:指南针效果

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...

  6. 【iOS】7.4 定位服务->3.1 地图框架MapKit 功能1:地图展示

    > 本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. --- > 本文相关目录: ================== 所属文集:[[ ...

  7. [android学习]android_gps定位服务简单实现

    前言 gps定位服务的学习是这段时间gps课程的学习内容,之前老师一直在将概念,今天终于是实践课(其实就是给了一个案例,让自己照着敲).不过在照着案列敲了两遍之后,发现老师的案例是在是太老了,并且直接 ...

  8. IOS 定位服务与地图的应用开发

    1.定位服务 现在的移动设备很多都提供定位服务,IOS设备提供3种不同定位途径: (1)WiFi定位,通过查询一个WiFi路由器的地理位置的信息,比较省电:IPhone,IPod touch和IPad ...

  9. Push Notification总结系列之移动客户端定位服务

    Push Notification系列概括: 1.Push Notification简介和证书说明及生成配置 2.Push Notification的iOS处理代码和Provider详解 3.Push ...

随机推荐

  1. 软件篇-01-为Jetson TX2扫清科研的障碍

    建议用vryL,GUI界面,功能更全,支持订阅. https://github.com/ShieldQiQi/vryL​github.com 下面的内容不用看了,除非你更喜欢命令行界面.   To r ...

  2. 技术面试问题汇总第005篇:猎豹移动反病毒工程师part5

    这是我当初接受面试的最后两个问题,当时,那位面试官问我对漏洞了解多少时,我说一点都不懂,问我懂不懂系统内核时,我同样只能说不知道.后来他跟我说,面试的考查重点不在于我所掌握的知识的广度,而是深度.这也 ...

  3. POJ3228二分最大流

    题意:       有n个点,每个点有两个权值,金子数量还有仓库容量,金子可以存在自己的仓库里或者是别的仓库里,仓库和仓库之间有距离,问所有金子都必须存到库里最大距离的最小是多少? 思路:       ...

  4. Win64 驱动内核编程-8.内核里的其他常用

    内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...

  5. Python爬虫之requests库的使用

    requests库 虽然Python的标准库中 urllib模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests宣传是 "HTTP for ...

  6. JVM垃圾回收的三种方式

    * 垃圾回收有三种方式 * 一.清除:将需要回收对象的内存空间存放在内存列表中,当需要为新对象分配内存的时候,就会从内存列表中拿取空间分配.不过这种分配方式有两个缺点 * 第一个缺点是内存空间碎片化, ...

  7. 北航OO(2020)第二单元博客作业

    第二单元第一次作业 多线程设计策略 第一次作业的想法是设计三个线程:输入线程,调度器线程以及电梯线程.输入线程获取请求并发送给调度器线程:调度器线程通过查询电梯线程的状态(等待.停靠以及移动),并综合 ...

  8. 服务治理演进剖析 & Service Mesh、 xDS核心原理梳理

    基于XDS协议实现控制面板与数据面板通信分享 基于这段时间在同程艺龙基础架构部的蹲坑,聊一聊微服务治理的核心难点.历史演进.最新动态, 以上内容属自我思考,不代表同程艺龙技术水准.如理解有偏差.理解不 ...

  9. VS·.Net WCF多项目调试方法

    阅文时长 | 0.12分钟 字数统计 | 252.8字符 主要内容 | 1.引言&背景 2.声明与参考资料 『VS·.Net WCF多项目调试方法』 编写人 | SCscHero 编写时间 | ...

  10. Journey to the future begins

    当提交申请的那一刻,我就更加确认了自己想要走的路,慢慢一路向上,追求自己想要的生活! 2021.5.18 wzb