Table of contents
The OA of the company often forgets to check in, and when I think of it, I get home, which is very annoying...
Refer to the official Android document, learn how to use addTestProvider, setTestProviderLocation, and simply specify the latitude and longitude GPS location. If you forget to check in, you can’t use this...
Operating environment
equipment: Xiaomi K30s
system: Android12
status: normal position
1. Judgment authority
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 = false
if (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 LocationManager
val providerStr = LocationManager.GPS_PROVIDER
val 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 = true
locationManager.setTestProviderEnabled(providerStr, false)
locationManager.removeTestProvider(providerStr)
} catch (e: SecurityException) {
canMockPosition = false
}
}
return canMockPosition
}
}
2. Start positioning (GPS position)
Through setTestProviderLocation(), set the GPS test location to realize the simulated map location. Pay attention to the update frequency of the location, it is not enough to set it once.
/**
* 开始位置
*/
@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 = 500f
location.time = System.currentTimeMillis();
location.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
binding.btStart.tag = "end"
try {
// 开启测试Provider
mLocManager.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. Off position
removeTestProvider is normal for my own mobile phone test call (Android11), and my colleague Android10 will crash ( abstract method "void android.location.LocationListener.onProviderDisabled() ). The exception that will appear on the document has been caught. I don't know why . Just remove it will crash, you can use the location normally...
Official API https://developer.android.google.cn/reference/kotlin/android/location/LocationManager?hl=en#removetestprovider
try {
mLocManager.removeTestProvider(LocationManager.GPS_PROVIDER)
} catch (e1: IllegalArgumentException) {
// 未成功addTestProvider时报错,为防万一有重复调用remove
Log.i(TAG, "initView: ${e1.message}")
} catch (e2: SecurityException) {
Log.i(TAG, "initView: ${e2.message}")
}
4. Realize the effect
The call is normal, OA obtains the simulated location, and so does the Gaode map