Android 模拟地图定位功能的实现

实现原理:

手机定位方式目前有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是否可用判断。

    /**
     * 模拟位置是否启用
     * 若启用,则addTestProvider
     */
    public boolean getUseMockPosition(Context context) {
        // Android 6.0以下,通过Setting.Secure.ALLOW_MOCK_LOCATION判断
        // Android 6.0及以上,需要【选择模拟位置信息应用】,未找到方法,因此通过addTestProvider是否可用判断
        boolean canMockPosition = (Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0)
                || Build.VERSION.SDK_INT > 22;
        if (canMockPosition && hasAddTestProvider == false) {
            try {
                for (String providerStr : mockProviders) {
                    LocationProvider provider = locationManager.getProvider(providerStr);
                    if (provider != null) {
                        locationManager.addTestProvider(
                                provider.getName()
                                , provider.requiresNetwork()
                                , provider.requiresSatellite()
                                , provider.requiresCell()
                                , provider.hasMonetaryCost()
                                , provider.supportsAltitude()
                                , provider.supportsSpeed()
                                , provider.supportsBearing()
                                , provider.getPowerRequirement()
                                , provider.getAccuracy());
                    } else {
                        if (providerStr.equals(LocationManager.GPS_PROVIDER)) {
                            locationManager.addTestProvider(
                                    providerStr
                                    , true, true, false, false, true, true, true
                                    , Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
                        } else if (providerStr.equals(LocationManager.NETWORK_PROVIDER)) {
                            locationManager.addTestProvider(
                                    providerStr
                                    , true, false, true, false, false, false, false
                                    , Criteria.POWER_LOW, Criteria.ACCURACY_FINE);
                        } else {
                            locationManager.addTestProvider(
                                    providerStr
                                    , false, false, false, false, true, true, true
                                    , Criteria.POWER_LOW, Criteria.ACCURACY_FINE);
                        }
                    }
                    locationManager.setTestProviderEnabled(providerStr, true);
                    locationManager.setTestProviderStatus(providerStr, LocationProvider.AVAILABLE, null, System.currentTimeMillis());
                }
                hasAddTestProvider = true;  // 模拟位置可用
                canMockPosition = true;
            } catch (SecurityException e) {
                canMockPosition = false;
            }
        }
        if (canMockPosition == false) {
            stopMockLocation();
        }
        return canMockPosition;
    }
```http://www.biyezuopin.vip
  接下来设置模拟经纬度数据:
```java
  // 模拟位置(addTestProvider成功的前提下)
  for (String providerStr : mockProviders) {
  Location mockLocation = new Location(providerStr);
  mockLocation.setLatitude(latitude);   // 维度(度)
  mockLocation.setLongitude(longitude);  // 经度(度)
  mockLocation.setAccuracy(0.1f);   // 精度(米)
  mockLocation.setTime(new Date().getTime());   // 本地时间
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
  }
    locationManager.setTestProviderLocation(providerStr, mockLocation);
  }
```http://www.biyezuopin.vip
  取消模拟定位方法:
```java
    /**
     * 取消位置模拟,以免启用模拟数据后无法还原使用系统位置
     * 若模拟位置未开启,则removeTestProvider将会抛出异常;
     * 若已addTestProvider后,关闭模拟位置,未removeTestProvider将导致系统GPS无数据更新;
     */
    public void stopMockLocation() {
        if (hasAddTestProvider) {
            for (String provider : mockProviders) {
                try {
                    locationManager.removeTestProvider(provider);
                } catch (Exception ex) {
                    // 此处不需要输出日志,若未成功addTestProvider,则必然会出错
                    // 这里是对于非正常情况的预防措施
                }
            }
            hasAddTestProvider = false;
        }
    }

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

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

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

 private LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(final Location location) {
            setLocationData(location);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };

    /**
     * 获取到模拟定位信息,并显示
     *
     * @param location 定位信息
     */
    private void setLocationData(Location location) {
        tvProvider.setText(location.getProvider());
        tvTime.setText(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(location.getTime())));
        tvLatitude.setText(location.getLatitude() + " °");
        tvLongitude.setText(location.getLongitude() + " °");
    }

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

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

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

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

(0)

相关推荐

  • Android仿微信朋友圈点击评论自动定位到相关行功能

    最近闲来无事,随便看看各种UI实现的代码 本文涉及到的相关代码已经上传到 https://github.com/r17171709/android_demo/tree/master/WeixinEditText 打开你的微信朋友圈,点击评论,你就会发现有一个小细节:文本输入框的高度恰好定位到这条信息的底部位置 这个实现起来其实很简单,咱们就来看看吧 最简单的RecyclerView 依然是先实现RecyclerView.跟朋友圈一样,我们也把头给加上去,这样我们在点第一条信息的时候,效果会更好一

  • Android仿微信通讯录滑动快速定位功能

    先给大家展示下效果图: 实现代码如下: 下面简单说下实现原理. public class IndexBar extends LinearLayout implements View.OnTouchListener { private static final String[] INDEXES = new String[]{"#", "A", "B", "C", "D", "E", &qu

  • Android之高德地图定位SDK集成及地图功能实现

    一:百度高德官方网站,然后去创建应用 网址:http://lbs.amap.com/ 1.找到控制台创建一个应用 2.添加key名称,注意命名规范,还有就是下面的SHA1和包名 3.点击右边的Gradle再选择signingReport下面会有个命令,稍等几分钟得到SHA1 4.添加包名 5.得到key 二:下载定位SDK,下载下来有地图SDK和定位SDK,然后导入项目,导入再Add As Library,so文件按自己需求来 下载地址:http://lbs.amap.com/api/andro

  • Android 百度地图定位实现仿钉钉签到打卡功能的完整代码

    导语 本章根据百度地图API,实现仿钉钉打卡功能.用到了基础地图.覆盖物.定位图层.陀螺仪方法.悬浮信息弹框. 百度地图API地址  :Android 地图SDK 请先注册注册百度账号和获取密钥,并实现地图显示出来.(注意:密钥.权限要设置) 另外,我得说明本章所下载官方Demo 和 导入的jar包和so文件.自定义下载即可,如下图: 接下来,一起看实现效果. 源码Git地址:BaiduMapApp 效果图 实现代码·三步骤 第一步:基础地图和方向传感器 类先实现方向传感器 implements

  • Android实现地理定位功能

    最近试着写了一下Android的定位,代码在下面,比较简单 首先需要的权限有 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name=

  • Android判断定位功能是否可用的方法

    定位功能是否可用由定位服务和定位权限共同决定: 判断定位服务: /** * 手机是否开启位置服务,如果没有开启那么所有app将不能使用定位功能 */ public static boolean isLocServiceEnable(Context context) { LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); boolean gps

  • arcgis android之定位功能的示例代码

    关于定位的功能,开发,很早之前就有做过百度的定位功能.起初是有想法把百度的Loc V3.2的定位SDK整合进来用.但是终归是想法,但是知道昨天,我问技术群,里面的一位朋友就说起了百度地位SDK整合进来的实现方法.顿时,我就思考了一会,随后就是很激动地操作起来.根据朋友给的一个demo.做了两天,终于算是真正将功能实现了.至于界面的美观或者样式的显示这个就偷懒掉了. http://developer.baidu.com/map/sdk-android.htm 这个是百度的SDK.帮助文档. 第一次

  • Android 模拟地图定位功能的实现

    实现原理: 手机定位方式目前有4种: 基站定位 WIFI定位 GPS定位 AGPS定位 本工程利用手机自带的"模拟位置"功能实现运行时修改LocationManager结果. 原理:使用android自带的调试api,模拟gps provider的结果.  Android 6.0系统以下,可以通过Setting.Secure.ALLOW_MOCK_LOCATION获取是否[允许模拟位置],当[允许模拟位置]开启时,可addTestProvider:   Android 6.0系统及以上

  • Android GPS定位测试(附效果图和示例)

    今天因为工作需要,把以前编写的一个GPS测试程序拿出来重新修改了一下.这个程序说起来有些历史了,是我11年编写的,那时候学了Android开发没多久,算是一个实验性的作品.现在工作需要,重新拿出来修整.同时发现我对android的GPS服务了解并不深,所以今天特意阅读了有关GPS服务的一些资料,把相关知识点记录下来. 本人做了GPS相关的嵌入式软件已经几年了,所以说起要做个测试GPS定位模块的程序,第一反应就是串口读取GPS模块的数据,然后解析GPS的NMEA格式数据.NMEA是一种标准化数据格

  • Android GPS定位详解及实例代码

    GPS定位是智能手机上一个比较有意思的功能,LBS等服务都有效的利用了GPS定位功能.本文就跟大家分享下Android开发中的GPS定位知识.      一.Android基础知识准备 1.Activity类 每一种移动开发环境都有自己的基类.如J2ME应用程序的基类是midlets,BREW的基类是applets,而Android程序的基类是Activity.这个activity为我们提供了对移动操作系统的基本功能和事件的访问.这个类包含了基本的构造方法,键盘处理,挂起来恢复功能,以及其他底层

  • Android Studio搜索功能(查找功能)及快捷键图文详解

    1.在当前窗口查找文本[Ctrl+F] F3 向下查找关键字出现位置 Shift+F3 向上一个关键字出现位置 2.在当前工程内查找文本[Ctrl+Shift+F] 先会弹出一个对话框,直接点击[find],开始在整个工程内查找该字符串 查找结果如下: 3.查找类[Ctrl+N] 4.查找文件[Ctrl+Shift+N] 5.查找项目中的方法或变量[Ctrl+Shift+Alt+N] 6.查找类/方法/变量引用的地方 先定位光标 右键选择"Find Usages"(快捷键Alt+F7)

  • Android原生定位服务LocationManager

    目录 前言 一.LocationManager的使用 二.混合定位 总结 前言 现在的应用,几乎每一个 App 都存在定位的逻辑,方便更好的推荐产品或服务,获取当前设备的经纬度是必备的功能了.有些 App 还是以LBS(基于位置服务)为基础来实现的,比如美团,饿了吗,不获取到位置都无法使用的. 有些同学觉得不就是获取到经纬度么,Android 自带的就有位置服务 LocationManager ,我们无需引入第三方服务,就可以很方便的实现定位逻辑. 确实 LocationManager 的使用很

  • IOS提醒用户重新授权打开定位功能

    iOS 8及以上版本最不为人知的一个特点是与应用设置的深层链接,用户可以根据APP的需要授权启用位置.通知.联系人.相机.日历以及健康等设置. 大多数应用程序仅仅是弹出一个包含操作指令的警示窗口,如"进入设置>隐私>位置>OUR_APP".例如,推特的应用程序有一个更为精致和友好的指示对话框,所以我就把它当做一个例子来使用(可惜大多数应用程序都会有一个非常糟糕的版本). 我现在以一个心情沮丧用户的身份写这个帖子,希望更多的iOS开发者能与用户设置建立直接的深层链接,尤

随机推荐