日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Android如何實現模擬定位

瀏覽:23日期:2022-09-19 08:06:33

在導航測試場景中經常需要定位模擬和路線回放,記錄下通過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 12)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) { /* ignore */}

同時在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的判斷。

@SystemApipublic 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();}@SystemApipublic 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 模擬定位的資料請關注好吧啦網其它相關文章!

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
免费在线观看日韩欧美| 亚洲欧美一区在线| 蜜桃视频在线观看一区二区| 成人三级高清视频在线看| 久久精品国产99国产精品| 国产激情欧美| 精品日产乱码久久久久久仙踪林| 精品亚洲成人| 日韩国产欧美一区二区| 久久婷婷av| 亚洲大全视频| 老牛影视一区二区三区| 亚洲欧美在线综合| 欧美永久精品| 精品视频在线观看网站| 国产h片在线观看| 久久精品成人| 日韩视频二区| 国产精品美女久久久| 石原莉奈在线亚洲二区| 亚洲精品乱码| 欧美精品97| 色偷偷偷在线视频播放| 亚洲婷婷免费| 伊人久久一区| 国产精品调教| 电影天堂国产精品| 午夜久久tv| 亚洲精品婷婷| 久久三级中文| 欧美91精品| 亚洲三级网站| 麻豆精品久久| 亚洲91久久| 日韩中出av| 国产精品99一区二区三| 亚洲午夜一级| 日韩中文一区二区| 精品少妇av| 欧美另类综合| 国产探花一区| 亚洲a在线视频| 亚洲精品九九| 日本不良网站在线观看| 蜜芽一区二区三区| 久久永久免费| 国产亚洲精品v| 国产精品www994| 99精品在线观看| 奇米狠狠一区二区三区| 香蕉视频亚洲一级| 日韩在线网址| 韩国精品主播一区二区在线观看 | 亚洲无线一线二线三线区别av| 免费在线看一区| 精品国产鲁一鲁****| 99视频在线精品国自产拍免费观看| 国产欧美一级| 九一精品国产| 国产精品美女午夜爽爽| www成人在线视频| 国产一区二区三区不卡视频网站 | 国产精品高潮呻吟久久久久| 久久久久蜜桃| 国产毛片精品| 国产精品免费看| 美女性感视频久久| 亚洲综合不卡| 福利一区二区免费视频| 涩涩涩久久久成人精品| 日韩欧美国产精品综合嫩v| 天海翼精品一区二区三区| 色一区二区三区| 午夜视频一区二区在线观看| 久久久久久久久久久9不雅视频| 青青草精品视频| 免费成人网www| 麻豆国产精品视频| 日本一区二区三区中文字幕| 亚洲午夜黄色| 国产一区二区三区不卡av| 亚洲精品大片| 亚洲一区二区三区免费在线观看| 在线一区av| 久久精品福利| 国产欧美亚洲精品a| 蜜臀91精品一区二区三区| 香蕉久久99| 国产福利亚洲| 日本国产欧美| 视频在线观看91| 九九综合在线| 天堂日韩电影| 四季av一区二区凹凸精品| 国产精品丝袜在线播放| 天堂俺去俺来也www久久婷婷| 国产精品美女| 国产亚洲午夜| 午夜国产精品视频免费体验区| 欧美日韩国产观看视频| 久久福利在线| 欧美天堂一区| 亚洲免费毛片| 丝袜美腿亚洲一区| 国产亚洲在线观看| 99热精品在线| 亚洲欧美视频一区二区三区| 1000部精品久久久久久久久| 日韩激情一区| 理论片午夜视频在线观看| 麻豆国产精品一区二区三区| 国产精品xxx在线观看| 国产精品igao视频网网址不卡日韩 | 久久国产精品久久久久久电车| 91看片一区| 国产在线视频欧美一区| 久久这里只有精品一区二区| 久久wwww| 久久精品资源| 麻豆一区二区99久久久久| 国产欧美亚洲一区| 国产美女久久| 国产精品日本一区二区不卡视频| 日本a级不卡| 久久激情av| 国产精品久久久久久久久久久久久久久 | 老司机精品在线| 卡一精品卡二卡三网站乱码| 精品美女视频 | 美女视频免费精品| 精品日产乱码久久久久久仙踪林| 精品视频亚洲| 日韩欧美一区二区三区在线视频| 亚洲三级欧美| 欧美午夜精品一区二区三区电影| 日韩欧美一区二区三区在线观看 | 中国字幕a在线看韩国电影| 国产成人免费精品| а√天堂8资源在线| 成人午夜亚洲| 日韩在线二区| 一本一道久久a久久精品蜜桃| 99国产精品自拍| 日韩av一二三| 欧美国产亚洲精品| 色爱综合网欧美| 免费成人网www| 亚洲精品成人一区| 免费亚洲一区| 91精品精品| 美日韩精品视频| 日韩黄色av| 国产成人精品一区二区三区在线| 黄色aa久久| 欧美在线资源| 青草综合视频| 福利一区和二区| av不卡在线看| 国产日韩在线观看视频| 国产精品毛片久久| 亚洲国产不卡| 日韩av网站在线观看| 久久婷婷国产| 1024精品一区二区三区| 蜜臀国产一区二区三区在线播放| 国产欧美91| 久久久久中文| 日韩激情综合| 日韩三区免费| 中文字幕日本一区二区| 美女在线视频一区| 欧美精品一卡| 国产精品一级| 激情偷拍久久| 久久激情综合网| 999久久久精品国产| 视频一区中文字幕精品| 国产精品久久久久久久久妇女| 美女网站一区| 国产情侣一区在线| 欧美 日韩 国产一区二区在线视频| 日本在线视频一区二区| 激情不卡一区二区三区视频在线| 五月精品视频| 国产精品久久久亚洲一区| 久久精品主播| 国产精品亲子伦av一区二区三区| 久久精品高清| 国产精品美女在线观看直播| 在线亚洲激情| 水蜜桃久久夜色精品一区| 蜜臀精品久久久久久蜜臀| 中文在线а√在线8| 亚洲精品伊人| 日韩中文在线播放| 欧美片网站免费| 日韩视频免费| 91亚洲自偷观看高清| 日韩精品视频一区二区三区| 日韩精品欧美|