iis服务器助手广告
返回顶部
首页 > 资讯 > 移动开发 >Android如何实现模拟定位
  • 762
分享到

Android如何实现模拟定位

2024-04-02 19:04:59 762人浏览 安东尼
摘要

目录一、Android模拟权限开启配置 1)Android 6.0以下开启模拟定位开关2)Android 6.0以上代码配置选择模拟定位的应用 二、Android模拟定位实现 1)模

在导航测试场景中经常需要定位模拟和路线回放,记录下通过LocationManager.setTestProviderLocation()方法实现模拟地位,如果要测试的应用不支持TestProviderLocation模拟位置输入,可以考虑从HAL层入手,hook系统默认的GPS实现。

一、Android模拟权限开启配置

在Android6.0以下的版本中,需要在设置中勾选模拟定位的开关,在6.0以上就改成了选择模拟定位的应用,对应的开启配置方式也不一样,相同的是在AndroidManifest.xml都需要配置以下两个权限:


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

1)Android 6.0以下开启模拟定位开关


Settings.Secure.putInt(getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 1);

通过这种方式去开启模拟定位需要在AndroidManifest.xml中配置以下系统权限,应用还需要经过系统签名,对于非系统应用不能通过这种实现方式。


android:sharedUserId="android.uid.system"

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

涉及到这种操作可以通过adb shell命令的方式配置来绕过系统权限配置:


adb shell settings put secure mock_location 1

2)Android 6.0以上代码配置选择模拟定位的应用

在6.0以上的Android版本就需要设置指定包名的mock_location权限为allow。


try {
    String mockLocationPkgName = getPackageName();
    PackageManager mPackageManager = getPackageManager();
    final ApplicationInfo ai = mPackageManager.getApplicationInfo(
            mockLocationPkgName, PackageManager.MATCH_DISABLED_COMPONENTS);
    AppOpsManager mAppsOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
    mAppsOpsManager.setMode(AppOpsManager.OPSTR_MOCK_LOCATION, ai.uid,
            mockLocationPkgName, AppOpsManager.MODE_ALLOWED);
} catch (PackageManager.NameNotFoundException e) {
    
}

同时在AndroidManifest.xml中还需要配置如下权限,可惜这种方式也是需要经过系统签名和源码一起编译,只有系统层级的应用才可以使用。


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

为了在设置界面模拟定位选项中显示模拟定位的应用,需要配置ACCESS_MOCK_LOCATION权限。


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

以上配置也可以通过adb shell命令去实现,<package> 参数用自己应用的包名替换。


adb shell appops set <package> android:mock_location allow

关闭模拟定位权限,用如下命令:


adb shell appops set <package> android:mock_location deny

要查询有哪些应用开启了模拟定位权限,用如下命令:


adb shell appops query-op android:mock_location allow

执行后会输出应用的包名列表参数。

二、Android模拟定位实现

1)模拟定位开关检查

首先是代码中先判断模拟定位权限是否开启,6.0以上的只能通过添加定位监听是否有异常来判断。


boolean mockPermission = false;
if (Build.VERSION.SDK_INT <= 22) {//6.0以下
    mockPermission = Settings.Secure.getInt(getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1;
} else {
    try {
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            mockPermission = false;            
            return;
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
            }
            @Override
            public void onStatusChanged(String s, int i, Bundle bundle) {
            }
            @Override
            public void onProviderEnabled(String s) {
            }
            @Override
            public void onProviderDisabled(String s) {
            }
        });
        mockPermission = true;
    } catch (SecurityException e) {
        mockPermission = false;
    }
}

可以看下添加定位监听的源码实现,以Android 7.0的源码实现做参考,LocationManager调用接口之后,最终是调用到LocationManagerService,在requestLocationUpdates 方法或 getLastLocation 方法中都有checkPackageName方法的调用


private void checkPackageName(String packageName) {
    if (packageName == null) {
        throw new SecurityException("invalid package name: " + packageName);
    }
    int uid = Binder.getCallingUid();
    String[] packages = mPackageManager.getPackagesForUid(uid);
    if (packages == null) {
        throw new SecurityException("invalid UID " + uid);
    }
    for (String pkg : packages) {
        if (packageName.equals(pkg)) return;
    }
    throw new SecurityException("invalid package name: " + packageName);
}

如果调用requestLocationUpdates方法的应用没有模拟定位的权限,就会报SecurityException异常,另外requestLocationUpdates需要在主线程中调用,如果在子线程中调用,还需要传一个looper参数,不然在实例化ListenerTransport的时候会报错。

看下ListenerTransport的构造函数,如果在子线程中添加监听,又没有传Loop,初始化mListenerHandler的时候就会报异常。


ListenerTransport(LocationListener listener, Looper looper) {
    mListener = listener;
    if (looper == null) {
        mListenerHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                _handleMessage(msg);
            }
        };
    } else {
        mListenerHandler = new Handler(looper) {
            @Override
            public void handleMessage(Message msg) {
                _handleMessage(msg);
            }
        };
    }
}

接着添加对应的Provider,设置开关状态为true,配置状态为AVAILABLE。


LocationProvider provider = locationManager.getProvider(LocationManager.GPS_PROVIDER);
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 {
    locationManager.addTestProvider(LocationManager.GPS_PROVIDER, true, true, false, false, true, true,
        true, Criteria.POWER_LOW, Criteria.ACCURACY_FINE);
}
locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
locationManager.setTestProviderStatus(LocationManager.GPS_PROVIDER, LocationProvider.AVAILABLE, null, System.currentTimeMillis());

2)setTestProviderLocation调用

调用代码示例如下,经纬度、车速、定位准确性、方位、海拔参数根据实际需求设置。


Location loc = new Location(LocationManager.GPS_PROVIDER);
loc.setLongitude(24.522301);
loc.setLatitude(118.115756);
loc.setSpeed(60);
loc.setAccuracy(Criteria.ACCURACY_HIGH);
loc.setBearing(0);
loc.setAltitude(0);
loc.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= 17) {
    loc.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER,loc);

来看下为什么需要设置elapsedRealtimeNanos和time参数。在SDK版本17以下,Location(Android 4.1.1)是没有setElapsedRealtimeNanos这个方法的,在SDK版本17开始,Location(Android 4.2)加了这个方法,在调用setTestProviderLocation设置定位信息的时候,Android SDK版本17以上会做定位参数是否完整的校验,17以下的版本自动做补足,17开始的版本直接抛异常。


public void setTestProviderLocation(String provider, Location loc) {
    if (!loc.isComplete()) {
        IllegalArgumentException e = new IllegalArgumentException(
            "Incomplete location object, missing timestamp or accuracy? " + loc);
        if (mContext.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN) {
            // just log on old platfORM (for backwards compatibility)
            Log.w(TAG, e);
            loc.makeComplete();
        } else {
            // really throw it!
            throw e;
        }
    }
    try {
        mService.setTestProviderLocation(provider, loc, mContext.getOpPackageName());
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

接着看下Location类中makeComplete和isComplete做的逻辑处理,isComplete里面有provider,Accuracy,mTime和mElapsedRealtimeNanos的判断。


@Systemapi
public void makeComplete() {
    if (mProvider == null) mProvider = "?";
    if (!hasAccuracy()) {
        mFieldsMask |= HAS_ACCURACY_MASK;
        Maccuracy = 100.0f;
    }
    if (mTime == 0) mTime = System.currentTimeMillis();
    if (mElapsedRealtimeNanos == 0) mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
}
@SystemApi
public boolean isComplete() {
    if (mProvider == null) return false;
    if (!hasAccuracy()) return false;
    if (mTime == 0) return false;
    if (mElapsedRealtimeNanos == 0) return false;
    return true;
}

以上是就是单个点的模拟定位实现,如果要实现路线回放模拟,只要在后台请求到路线定位点数组数据之后,每隔1秒刷新调用setTestProviderLocation接口就可以了。

在模拟定位操作完毕之后,需要移除模拟定位对象,避免定位信息还是使用模拟定位接口的参数,如果没有移除下一次使用的时候又调用添加同名的Provider也会抛异常。


locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);

以上就是Android如何实现模拟定位的详细内容,更多关于Android 模拟定位的资料请关注编程网其它相关文章!

--结束END--

本文标题: Android如何实现模拟定位

本文链接: https://www.lsjlt.com/news/125164.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android如何实现模拟定位
    目录一、Android模拟权限开启配置 1)Android 6.0以下开启模拟定位开关2)Android 6.0以上代码配置选择模拟定位的应用 二、Android模拟定位实现 1)模...
    99+
    2024-04-02
  • Android 模拟地图定位功能的实现
    实现原理: 手机定位方式目前有4种: 基站定位WIFI定位GPS定位AGPS定位 本工程利用手机自带的"模拟位置"功能实现运行时修改LocationManager...
    99+
    2024-04-02
  • CSS如何实现模拟position的fixed页面定位效果
    这篇文章主要介绍CSS如何实现模拟position的fixed页面定位效果,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体实现方法如下:代码如下:<!DOCTYPE html...
    99+
    2024-04-02
  • android如何实现加密参数定位
    这篇文章给大家分享的是有关android如何实现加密参数定位的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在逆向一个Android程序时,如果只是盲目的分析需要阅读N多代码才能找到程序的关键点或Hook点,本文将...
    99+
    2023-06-14
  • Android 简单服务定位器模式实现
    目录引入API使用依赖注入(Dependency Injection)和服务定位器(Service Locator)是实现控制反转(Inversion of Control)的两种主...
    99+
    2024-04-02
  • Android listview如何实现定位到上次显示的位置
    这篇文章主要为大家展示了“Android listview如何实现定位到上次显示的位置”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Android listview如何实现定位到上次显示的位置”...
    99+
    2023-05-30
    android listview
  • 如何使用Android实现地理定位功能
    这篇文章给大家分享的是有关如何使用Android实现地理定位功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。首先需要的权限有<uses-permission android:name="...
    99+
    2023-05-30
    android
  • Android如何自定义模拟时钟控件
    本文小编为大家详细介绍“Android如何自定义模拟时钟控件”,内容详细,步骤清晰,细节处理妥当,希望这篇“Android如何自定义模拟时钟控件”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。自定义view&...
    99+
    2023-06-26
  • Android实现模拟搜索功能
    本文实例为大家分享了Android实现模拟搜索功能的具体代码,供大家参考,具体内容如下 先看效果图,合适了再接着往下看: 我们看到的这个页面,是由两部分组成,顶部的自定义的搜索框,...
    99+
    2024-04-02
  • 怎么用CSS实现模拟position的fixed页面定位效果
    这篇文章主要讲解了“怎么用CSS实现模拟position的fixed页面定位效果”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用CSS实现模拟posit...
    99+
    2024-04-02
  • ios不越狱虚拟定位教程:如何在iOS设备上实现无需越狱的虚拟定位
    iOS不越狱虚拟定位教程:打开iPhone的“设置”,然后点击“隐私”,选择“定位服务”; iOS不越狱虚拟定位教程: 首先,打开iPhone的“设置”,然后点击“隐私”,选择“定位服务”; 在定位服务页面,找到“系统服务”,点击进入; 在...
    99+
    2023-10-02
    ios cocoa macos
  • HTML5如何实现地理定位
    这篇文章主要介绍了HTML5如何实现地理定位,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。地理位置(Geolocation)是 H...
    99+
    2024-04-02
  • css绝对定位如何实现
    本文小编为大家详细介绍“css绝对定位如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“css绝对定位如何实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一.基本概念:如果说相对定位没有脱离文档流,相对于...
    99+
    2023-07-04
  • Css如何实现绝对定位
    这篇文章将为大家详细讲解有关Css如何实现绝对定位,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。设置为绝对定位的元素框从文档流完全删除,并相对于其包含块定位,包含块可能是...
    99+
    2024-04-02
  • ajax如何实现手机定位
    这篇文章将为大家详细讲解有关ajax如何实现手机定位,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。目前的版本只是demo,仍有几个问题需要完善一下,问题如下:1,如何将经...
    99+
    2024-04-02
  • Css如何实现相对定位
    小编给大家分享一下Css如何实现相对定位,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!相对定位指的是设置为相对定位的元素框会偏移...
    99+
    2024-04-02
  • 如何在Html5中实现定位
    今天就跟大家聊聊有关如何在Html5中实现定位,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. 在浏览器中,通过腾讯地图jsapi获取位置1 在项目的 html 模版文件中引入腾讯...
    99+
    2023-06-09
  • php如何实现定位功能
    这篇文章主要介绍“php如何实现定位功能”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“php如何实现定位功能”文章能帮助大家解决问题。php实现定位功能的方法:1、注册成为百度用户,成为地图开放平台...
    99+
    2023-07-04
  • java如何实现定位功能
    Java可以通过使用GPS或Wi-Fi来实现定位功能。以下是几种实现定位功能的方法:1. 使用GPS:Java可以通过调用系统的GP...
    99+
    2023-09-21
    java
  • Android如何模拟实现华为系统升级进度条
    这篇文章主要为大家展示了“Android如何模拟实现华为系统升级进度条”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Android如何模拟实现华为系统升级进度条”这篇文章吧。下面开始讲解虚线进度...
    99+
    2023-06-28
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作