经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Android 模拟地图定位功能的实现
来源:jb51  时间:2022/2/28 11:23:36  对本文有异议

实现原理:

手机定位方式目前有4种:

  • 基站定位
  • WIFI定位
  • GPS定位
  • AGPS定位

本工程利用手机自带的"模拟位置"功能实现运行时修改LocationManager结果。

原理:使用android自带的调试api,模拟gps provider的结果。 

Android 6.0系统以下,可以通过Setting.Secure.ALLOW_MOCK_LOCATION获取是否【允许模拟位置】,当【允许模拟位置】开启时,可addTestProvider;

  Android 6.0系统及以上,弃用Setting.Secure.ALLOW_MOCK_LOCATION变量,没有【允许模拟位置】选项,
增加【选择模拟位置信息应用】,此时需要选择当前应用,才可以addTestProvider,
但未找到获取当前选择应用的方法,因此通过addTestProvider是否成功来判断是否可用模拟位置。

代码分析:

MockLocationManager:模拟地址管理类
首先通过Android系统模拟位置管理器LocationManager获取系统模拟位置服务,Android 6.0以下,通过Setting.Secure.ALLOW_MOCK_LOCATION判断是否可模拟位置,Android 6.0及以上,需要【选择模拟位置信息应用】,未找到方法,因此通过addTestProvider是否可用判断。

  1. ? ? /**
  2. ? ? ?* 模拟位置是否启用
  3. ? ? ?* 若启用,则addTestProvider
  4. ? ? ?*/
  5. ? ? public boolean getUseMockPosition(Context context) {
  6. ? ? ? ? // Android 6.0以下,通过Setting.Secure.ALLOW_MOCK_LOCATION判断
  7. ? ? ? ? // Android 6.0及以上,需要【选择模拟位置信息应用】,未找到方法,因此通过addTestProvider是否可用判断
  8. ? ? ? ? boolean canMockPosition = (Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0)
  9. ? ? ? ? ? ? ? ? || Build.VERSION.SDK_INT > 22;
  10. ? ? ? ? if (canMockPosition && hasAddTestProvider == false) {
  11. ? ? ? ? ? ? try {
  12. ? ? ? ? ? ? ? ? for (String providerStr : mockProviders) {
  13. ? ? ? ? ? ? ? ? ? ? LocationProvider provider = locationManager.getProvider(providerStr);
  14. ? ? ? ? ? ? ? ? ? ? if (provider != null) {
  15. ? ? ? ? ? ? ? ? ? ? ? ? locationManager.addTestProvider(
  16. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? provider.getName()
  17. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.requiresNetwork()
  18. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.requiresSatellite()
  19. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.requiresCell()
  20. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.hasMonetaryCost()
  21. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.supportsAltitude()
  22. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.supportsSpeed()
  23. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.supportsBearing()
  24. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.getPowerRequirement()
  25. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , provider.getAccuracy());
  26. ? ? ? ? ? ? ? ? ? ? } else {
  27. ? ? ? ? ? ? ? ? ? ? ? ? if (providerStr.equals(LocationManager.GPS_PROVIDER)) {
  28. ? ? ? ? ? ? ? ? ? ? ? ? ? ? locationManager.addTestProvider(
  29. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? providerStr
  30. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , true, true, false, false, true, true, true
  31. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
  32. ? ? ? ? ? ? ? ? ? ? ? ? } else if (providerStr.equals(LocationManager.NETWORK_PROVIDER)) {
  33. ? ? ? ? ? ? ? ? ? ? ? ? ? ? locationManager.addTestProvider(
  34. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? providerStr
  35. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , true, false, true, false, false, false, false
  36. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , Criteria.POWER_LOW, Criteria.ACCURACY_FINE);
  37. ? ? ? ? ? ? ? ? ? ? ? ? } else {
  38. ? ? ? ? ? ? ? ? ? ? ? ? ? ? locationManager.addTestProvider(
  39. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? providerStr
  40. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , false, false, false, false, true, true, true
  41. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? , Criteria.POWER_LOW, Criteria.ACCURACY_FINE);
  42. ? ? ? ? ? ? ? ? ? ? ? ? }
  43. ? ? ? ? ? ? ? ? ? ? }
  44. ? ? ? ? ? ? ? ? ? ? locationManager.setTestProviderEnabled(providerStr, true);
  45. ? ? ? ? ? ? ? ? ? ? locationManager.setTestProviderStatus(providerStr, LocationProvider.AVAILABLE, null, System.currentTimeMillis());
  46. ? ? ? ? ? ? ? ? }
  47. ? ? ? ? ? ? ? ? hasAddTestProvider = true; ?// 模拟位置可用
  48. ? ? ? ? ? ? ? ? canMockPosition = true;
  49. ? ? ? ? ? ? } catch (SecurityException e) {
  50. ? ? ? ? ? ? ? ? canMockPosition = false;
  51. ? ? ? ? ? ? }
  52. ? ? ? ? }
  53. ? ? ? ? if (canMockPosition == false) {
  54. ? ? ? ? ? ? stopMockLocation();
  55. ? ? ? ? }
  56. ? ? ? ? return canMockPosition;
  57. ? ? }
  58. ```http://www.biyezuopin.vip
  59.   接下来设置模拟经纬度数据:
  60. ```java
  61. ? // 模拟位置(addTestProvider成功的前提下)
  62. ? for (String providerStr : mockProviders) {
  63. ? Location mockLocation = new Location(providerStr);
  64. ? mockLocation.setLatitude(latitude); ? // 维度(度)
  65. ? mockLocation.setLongitude(longitude); ?// 经度(度)
  66. ? mockLocation.setAccuracy(0.1f); ? // 精度(米)
  67. ? mockLocation.setTime(new Date().getTime()); ? // 本地时间
  68. ? if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
  69. ? ? mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
  70. ? }
  71. ? ? locationManager.setTestProviderLocation(providerStr, mockLocation);
  72. ? }
  73. ```http://www.biyezuopin.vip
  74.   取消模拟定位方法:
  75. ```java
  76. ? ? /**
  77. ? ? ?* 取消位置模拟,以免启用模拟数据后无法还原使用系统位置
  78. ? ? ?* 若模拟位置未开启,则removeTestProvider将会抛出异常;
  79. ? ? ?* 若已addTestProvider后,关闭模拟位置,未removeTestProvider将导致系统GPS无数据更新;
  80. ? ? ?*/
  81. ? ? public void stopMockLocation() {
  82. ? ? ? ? if (hasAddTestProvider) {
  83. ? ? ? ? ? ? for (String provider : mockProviders) {
  84. ? ? ? ? ? ? ? ? try {
  85. ? ? ? ? ? ? ? ? ? ? locationManager.removeTestProvider(provider);
  86. ? ? ? ? ? ? ? ? } catch (Exception ex) {
  87. ? ? ? ? ? ? ? ? ? ? // 此处不需要输出日志,若未成功addTestProvider,则必然会出错
  88. ? ? ? ? ? ? ? ? ? ? // 这里是对于非正常情况的预防措施
  89. ? ? ? ? ? ? ? ? }
  90. ? ? ? ? ? ? }
  91. ? ? ? ? ? ? hasAddTestProvider = false;
  92. ? ? ? ? }
  93. ? ? }

注册位置服务,获取系统位置

  1. ? ? ? // 注册位置服务,获取系统位置
  2. ? ? ? ? if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
  3. ? ? ? ? ? ? // ? ?ActivityCompat#requestPermissions
  4. ? ? ? ? ? ? // here to request the missing permissions, and then overriding
  5. ? ? ? ? ? ? // ? public void onRequestPermissionsResult(int requestCode, String[] permissions,
  6. ? ? ? ? ? ? // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int[] grantResults)
  7. ? ? ? ? ? ? // to handle the case where the user grants the permission. See the documentation
  8. ? ? ? ? ? ? // for ActivityCompat#requestPermissions for more details.
  9. ? ? ? ? ? ? return;
  10. ? ? ? ? }
  11. ? ? ? ? mockLocationManager.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);

最后通过LocationListener.onLocationChanged()回调方法获取GPS定位数据:

  1. ?private LocationListener locationListener = new LocationListener() {
  2. ? ? ? ? @Override
  3. ? ? ? ? public void onLocationChanged(final Location location) {
  4. ? ? ? ? ? ? setLocationData(location);
  5. ? ? ? ? }
  6.  
  7. ? ? ? ? @Override
  8. ? ? ? ? public void onStatusChanged(String provider, int status, Bundle extras) {
  9.  
  10. ? ? ? ? }
  11.  
  12. ? ? ? ? @Override
  13. ? ? ? ? public void onProviderEnabled(String provider) {
  14.  
  15. ? ? ? ? }
  16.  
  17. ? ? ? ? @Override
  18. ? ? ? ? public void onProviderDisabled(String provider) {
  19.  
  20. ? ? ? ? }
  21. ? ? };
  22.  
  23. ? ? /**
  24. ? ? ?* 获取到模拟定位信息,并显示
  25. ? ? ?*
  26. ? ? ?* @param location 定位信息
  27. ? ? ?*/
  28. ? ? private void setLocationData(Location location) {
  29. ? ? ? ? tvProvider.setText(location.getProvider());
  30. ? ? ? ? tvTime.setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(location.getTime())));
  31. ? ? ? ? tvLatitude.setText(location.getLatitude() + " °");
  32. ? ? ? ? tvLongitude.setText(location.getLongitude() + " °");
  33. ? ? }

使用模拟定位需先开启系统设置中的模拟位置:

Android 6.0 以下:【开发者选项 -> 允许模拟位置】

Android 6.0 及以上:【开发者选项 -> 选择模拟位置信息应用】

到此这篇关于Android 模拟地图定位功能的实现的文章就介绍到这了,更多相关Android 模拟地图定位功能内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号