目录
- 1.判断权限
- 2.开始定位(GPS位置)
- 3.关闭位置
- 4.实现效果
公司OA经常忘了打卡,想起来就到家了,这就很烦…
参考Android官方文档,学习使addTestProvider,setTestProviderLocation,实现简单指定经纬度GPS位置,要是忘了打卡,可不能用这个…
运行环境
设备:小米K30s
系统:Android12
状态:位置正常
1.判断权限
AndroidManifest.xml
<!--MOCK--><uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/><!--网络--><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><!--GPS--><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
object MockLocationUtils {/*** 是否选择应用* Android 6.0以下,通过Setting.Secure.ALLOW_MOCK_LOCATION判断* Android 6.0及以上,需要【开发者选项 选择应用】通过addTestProvider是否可用判断* @param context Context .* @return Boolean .*/@SuppressLint("WrongConstant")fun isAllowMockLocation(context: Context): Boolean {var canMockPosition = falseif (Build.VERSION.SDK_INT <= 22) { //6.0以下canMockPosition = Settings.Secure.getInt(context.contentResolver,Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0} else {try {val locationManager =context.getSystemService(Context.LOCATION_SERVICE) as LocationManagerval providerStr = LocationManager.GPS_PROVIDERval provider = locationManager.getProvider(providerStr)if (provider != null) {locationManager.addTestProvider(provider.name,provider.requiresNetwork(),provider.requiresSatellite(),provider.requiresCell(),provider.hasMonetaryCost(),provider.supportsAltitude(),provider.supportsSpeed(),provider.supportsBearing(),provider.powerRequirement,provider.accuracy)} else {locationManager.addTestProvider(providerStr,true,true,false,false,true,true,true,Criteria.POWER_HIGH,Criteria.ACCURACY_FINE)}locationManager.setTestProviderEnabled(providerStr, true)locationManager.setTestProviderStatus(providerStr,LocationProvider.AVAILABLE,null,System.currentTimeMillis())// 可用canMockPosition = truelocationManager.setTestProviderEnabled(providerStr, false)locationManager.removeTestProvider(providerStr)} catch (e: SecurityException) {canMockPosition = false}}return canMockPosition}
}
2.开始定位(GPS位置)
通过setTestProviderLocation(),设置GPS测试位置,实现模拟地图位置.注意位置的更新频率,不是设置一次就行.
/*** 开始位置*/@SuppressLint("MissingPermission")private fun startLocation() {val provider = mLocManager.getProvider(LocationManager.GPS_PROVIDER)if (provider != null) {mLocManager.addTestProvider(provider.getName(),provider.requiresNetwork(),provider.requiresSatellite(),provider.requiresCell(),provider.hasMonetaryCost(),provider.supportsAltitude(),provider.supportsSpeed(),provider.supportsBearing(),provider.getPowerRequirement(),provider.getAccuracy())} else {//Log.i(TAG, "startLocation: provider=null")Toast.makeText(this, "LocationProvider", Toast.LENGTH_LONG).show()return}/* 创建新的Location对象,并设定必要的属性值 */val location = Location(LocationManager.GPS_PROVIDER)location.latitude = CoordinateUtils.WGSLat(lat, lng)location.longitude = CoordinateUtils.WGSLon(lat, lng)location.accuracy = 500flocation.time = System.currentTimeMillis();location.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();binding.btStart.tag = "end"try {// 开启测试ProvidermLocManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true)mLocManager.setTestProviderStatus(LocationManager.GPS_PROVIDER,LocationProvider.AVAILABLE,null,System.currentTimeMillis())mLocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,10.0f,object : LocationListener {override fun onLocationChanged(location: Location) {Log.i(TAG,"onLocationChanged: lat:" + location.latitude + "lng:${location.longitude}")}})lifecycleScope.launch {while (binding.btStart.tag == "end") {delay(500)// 设置最新位置,一定要在requestLocationUpdate完成后进行,才能收到监听if (binding.btStart.tag == "end") {mLocManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, location);Log.i(TAG, "startLocation: " + System.currentTimeMillis())}}}binding.btStart.text = "关闭"binding.btStart.setBackgroundColor(Color.RED)binding.btStart.tag = "end"} catch (e: Exception) {Toast.makeText(this, "开启定位失败${e.message}", Toast.LENGTH_LONG).show()//binding.btStart.text = "开始"binding.btStart.setBackgroundColor(Color.parseColor("#FF6200EE"))binding.btStart.tag = "start"}}
3.关闭位置
removeTestProvider我自己的手机测试调用是正常的(Android11),在我同事Android10会crash(abstract method "void android.location.LocationListener.onProviderDisabled()).已经捕捉了文档上会出现的异常.不知道为啥. 只是移除会crash,可以正常使用位置…
官方APIhttps://developer.android.google.cn/reference/kotlin/android/location/LocationManager?hl=en#removetestprovider
try {mLocManager.removeTestProvider(LocationManager.GPS_PROVIDER)} catch (e1: IllegalArgumentException) {// 未成功addTestProvider时报错,为防万一有重复调用removeLog.i(TAG, "initView: ${e1.message}")} catch (e2: SecurityException) {Log.i(TAG, "initView: ${e2.message}")}
4.实现效果
调用正常,OA 获取的是这个模拟的位置,高德地图也是