Android analog map gps positioning


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
insert image description here

 				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

insert image description hereinsert image description here

Guess you like

Origin blog.csdn.net/qq_35193677/article/details/126520022