Android アナログ マップ GPS ポジショニング


会社のOAはチェックインを忘れることが多く、そういえば家に帰るのが面倒くさい…
Androidの公式ドキュメントを参考にaddTestProvider、setTestProviderLocationの使い方を学び、緯度と経度 GPS 位置情報 チェックインし忘れたら使えない…
動作環境
機器:Xiaomi 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 = 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.測位開始(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 = 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. オフ位置

removeTestProvider は、自分の携帯電話のテスト コール (Android11) では正常であり、同僚の Android10 はクラッシュします (抽象メソッド "void android.location.LocationListener.onProviderDisabled() ")。ドキュメントに表示される例外がキャッチされました。理由はわかりません.削除するだけでクラッシュします.場所は正常に使用できます...
公式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.効果を実感する

呼び出しは正常で、OA はシミュレートされた位置を取得し、Gaode マップも取得します。

ここに画像の説明を挿入ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_35193677/article/details/126520022