Android 使用模拟位置(支持Android 6.0) - Go语言中文社区

Android 使用模拟位置(支持Android 6.0)


开启系统设置中的模拟位置

  • Android 6.0 以下:【开发者选项 -> 允许模拟位置】

    允许模拟位置

  • Android 6.0 及以上:【开发者选项 -> 选择模拟位置信息应用】

    选择模拟位置信息应用


AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

判断是否开启了系统模拟位置

  • Android 6.0 以下:使用Settings.Secure.ALLOW_MOCK_LOCATION判断。

    // Android 6.0 以下:是否开启【允许模拟位置】
    boolean canMockPosition = Settings.Secure.getInt(getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0
  • Android 6.0 及以上:没有【允许模拟位置】选项,同时弃用了Settings.Secure.ALLOW_MOCK_LOCATION,无法通过上面的方法判断。增加了【选择模拟位置信息应用】的方法,需要选择使用模拟位置的应用。但是不知道怎么获取当前选择的应用,因此通过是否能够成功执行addTestProvider方法来进行判断,如果没有选择当前的应用,则addTestProvider会抛出异常。(有没有人知道,有没有人知道。。。)

    boolean hasAddTestProvider = false;
    boolean canMockPosition = (Settings.Secure.getInt(getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0)
            || Build.VERSION.SDK_INT > 22;
    if (canMockPosition && hasAddTestProvider == false) {
        try {
            String providerStr = LocationManager.GPS_PROVIDER;
            LocationProvider provider = locationManager.getProvider(providerStr);
            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(
                        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());
    
            // 模拟位置可用
            hasAddTestProvider = true;
            canMockPosition = true;
        } catch (SecurityException e) {
            canMockPosition = false;
        }
    }

模拟位置

private class RunnableMockLocation implements Runnable {

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(INTERVEL);

                if (hasAddTestProvider() == false) {
                    continue;
                }

                try {
                    // 模拟位置(addTestProvider成功的前提下)
                    String providerStr = LocationManager.GPS_PROVIDER;
                    Location mockLocation = new Location(providerStr);
                    mockLocation.setLatitude(22);   // 维度(度)
                    mockLocation.setLongitude(113);  // 经度(度)
                    mockLocation.setAltitude(30);    // 高程(米)
                    mockLocation.setBearing(180);   // 方向(度)
                    mockLocation.setSpeed(10);    //速度(米/秒)
                    mockLocation.setAccuracy(0.1f);   // 精度(米)
                    mockLocation.setTime(new Date().getTime());   // 本地时间 
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                        mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
                    }
                    locationManager.setTestProviderLocation(providerStr, mockLocation);
                } catch (Exception e) {
                    // 防止用户在软件运行过程中关闭模拟位置或选择其他应用
                    stopMockLocation();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

停止模拟位置

/**
 * 停止模拟位置,以免启用模拟数据后无法还原使用系统位置
 * 若模拟位置未开启,则removeTestProvider将会抛出异常;
 * 若已addTestProvider后,关闭模拟位置,未removeTestProvider将导致系统GPS无数据更新;
 */
public void stopMockLocation() {
    if (hasAddTestProvider) {
        try {
            locationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
        } catch (Exception ex) {
            // 若未成功addTestProvider,或者系统模拟位置已关闭则必然会出错
        }
        hasAddTestProvider = false;
    }
}

Android Studio Project

Android模拟位置

系统原生位置

模拟位置

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/doris_d/article/details/51384285
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-13 13:57:10
  • 阅读 ( 723 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢