【问题标题】:How to SET Android Mock GPS location?如何设置 Android 模拟 GPS 位置?
【发布时间】:2016-07-07 17:28:31
【问题描述】:

说明

我在尝试使用 android 模拟位置时遇到问题,我的主要目标是将 android GPS 设置为认为我们在不同的位置,也就是假 GPS。

当前尝试

我目前尝试了两种不同的类似解决方案,这两个网站都提供:

这两个教程都是 2012 年的,我不知道它们是否已经过时或者我很难实施它们。

编码开发

首先我确保我有权限:

  1. ACCESS_COARSE_LOCATION
  2. ACCESS_FINE_LOCATION
  3. ACCESS_MOCK_LOCATION *

注意:1 和 2 都被选中,如果它们不可用,我使用 requestPermissions 函数请求许可。第三个是不能问的,实际上只能在debug模式下通过AndroidManifest.xml添加。

我还确保在设置>开发者选项>允许模拟位置中选择了我的应用程序。

毕竟,我已经制作了这个我尝试通过 OnCreate 方法或按钮的 OnClick 调用的函数:

public void mockLocation(){
    LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    Criteria criteria = new Criteria();
    criteria.setAccuracy( Criteria.ACCURACY_FINE );
    String mocLocationProvider = lm.getBestProvider( criteria, true );
    if ( mocLocationProvider == null ) {
        Toast.makeText(getApplicationContext(), "No location provider found!", Toast.LENGTH_SHORT).show();
        return;
    }
    lm.addTestProvider(mocLocationProvider, false, false,
            false, false, true, true, true, 0, 5);
    lm.setTestProviderEnabled(mocLocationProvider, true);

    Location loc = new Location(mocLocationProvider);
    Location mockLocation = new Location(mocLocationProvider); // a string
    mockLocation.setLatitude(-26.902038);  // double
    mockLocation.setLongitude(-48.671337);
    mockLocation.setAltitude(loc.getAltitude());
    mockLocation.setTime(System.currentTimeMillis());
    lm.setTestProviderLocation( mocLocationProvider, mockLocation);
    Toast.makeText(getApplicationContext(), "Working", Toast.LENGTH_SHORT).show();
}

如果我以这种方式编译和测试,我将收到 Toast:“未找到位置提供程序!”。但是如果我将 mocLocationProvider 更改为:

String mocLocationProvider = LocationManager.NETWORK_PROVIDER;

我得到 APP 崩溃,在 LogCat 中它说在这一行期间崩溃了:

lm.setTestProviderLocation(mocLocationProvider, mockLocation);

所以我目前别无选择,不知道如何前进。

【问题讨论】:

  • 有时卡住了,您尝试重新启动设备。在检查 GPS 的状态时我也遇到了这个问题,尽管我打开了它,但它总是返回 false。并调试它注意到 Not found gps provider。所以重启设备,它消失了

标签: java android android-studio gps


【解决方案1】:

你必须设置 第一:

允许在设置中模拟位置

第二次设置权限:

ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION ACCESS_MOCK_LOCATION

第三次使用这个方法:

setMock(some_lat,some_lon,some accuracy);

private void setMock(double latitude, double longitude, float accuracy) {
 locMgr.addTestProvider (LocationManager.GPS_PROVIDER,
            "requiresNetwork" == "",
            "requiresSatellite" == "",
            "requiresCell" == "",
            "hasMonetaryCost" == "",
            "supportsAltitude" == "",
            "supportsSpeed" == "",
            "supportsBearing" == "",
            android.location.Criteria.POWER_LOW,
            android.location.Criteria.ACCURACY_FINE);

    Location newLocation = new Location(LocationManager.GPS_PROVIDER);

    newLocation.setLatitude(latitude);
    newLocation.setLongitude(longitude);
    newLocation.setAccuracy(accuracy);
    newLocation.setAltitude(0);
    newLocation.setAccuracy(500);
    newLocation.setTime(System.currentTimeMillis());
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        newLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
    }
    locMgr.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);

    locMgr.setTestProviderStatus(LocationManager.GPS_PROVIDER,
            LocationProvider.AVAILABLE,
            null,System.currentTimeMillis());

    locMgr.setTestProviderLocation(LocationManager.GPS_PROVIDER, newLocation);}

【讨论】:

    【解决方案2】:

    您必须设置准确度和 ElapsedRealtimeNanos 值

    location.setAccuracy(...);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
    }
    

    否则会抛出 IllegalArgumentException。

    @throws IllegalArgumentException 如果位置不完整

    更新

    如果你模拟网络提供商

    String mocLocationProvider = LocationManager.NETWORK_PROVIDER;
    

    然后您将通过网络提供商收到模拟位置,

    LocationListener listener = new LocationListener(){
        ...
        void onLocationChanged(Location location){
    
        }
    };
    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, ..., listener);
    

    并且每当您调用 setTestProviderLocation 方法时,都会触发 onLocationChanged 回调!

    【讨论】:

    • 好吧,它给了我最后的祝酒词,这意味着它可以正常工作,您的解决方案修复了崩溃!但是当我测试它时,我的位置没有改变,你知道发生了什么吗?
    • 我不明白为什么需要这个新的更新,反正我加了还是不行,是不是得在onLocationChanged里面加点东西?另外,我可以在其中添加@Override 吗?
    • 无需提出位置请求,我只是想向您展示它是如何工作的。无论如何,当您调用 setTestProviderLocation 方法时,它会模拟传入的提供程序。意味着,如果您设置 String mocLocationProvider = LocationManager.NETWORK_PROVIDER;然后网络提供商将返回模拟位置。
    • 如果要接收模拟gps位置,必须设置String mocLocationProvider = LocationManager.GPS_PROVIDER;
    • Blackkara,我可以在 Google 地图中看到“模拟位置”的结果吗?这种“虚假位置”是否会影响其他应用?
    【解决方案3】:

    来自@Blackkara 的回答和 cmets,这是最终代码,并且 不要忘记将定位模式设置为仅设备(GPS)

        LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        Criteria criteria = new Criteria();
        criteria.setAccuracy( Criteria.ACCURACY_FINE );
    
        String mocLocationProvider = LocationManager.GPS_PROVIDER;//lm.getBestProvider( criteria, true );
    
        if ( mocLocationProvider == null ) {
            Toast.makeText(getApplicationContext(), "No location provider found!", Toast.LENGTH_SHORT).show();
            return;
        }
        lm.addTestProvider(mocLocationProvider, false, false,
                false, false, true, true, true, 0, 5);
        lm.setTestProviderEnabled(mocLocationProvider, true);
    
        Location loc = new Location(mocLocationProvider);
        Location mockLocation = new Location(mocLocationProvider); // a string
        mockLocation.setLatitude(-26.902038);  // double
        mockLocation.setLongitude(-48.671337);
        mockLocation.setAltitude(loc.getAltitude());
        mockLocation.setTime(System.currentTimeMillis());
        mockLocation.setAccuracy(1);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
        }
        lm.setTestProviderLocation( mocLocationProvider, mockLocation);
        Toast.makeText(getApplicationContext(), "Working", Toast.LENGTH_SHORT).show();
    

    【讨论】:

      猜你喜欢
      • 2017-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-29
      • 2011-09-11
      • 1970-01-01
      • 2016-08-13
      • 2018-11-18
      相关资源
      最近更新 更多