java 如何设置 Android Mock GPS 位置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38251741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 03:15:41  来源:igfitidea点击:

How to SET Android Mock GPS location?

javaandroidandroid-studiogps

提问by Guilherme Garcia da Rosa

Description

描述

I'm having a issue while trying to use android mock locations, my main goal is to set the android GPS into thinking we are in a different spot, AKA fake GPS.

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

Current attempts

当前尝试

I have currently tried two different similar solutions, avaiable in both this websites:

我目前尝试了两种不同的类似解决方案,可在这两个网站上使用:

Both tutorials are from 2012, I don't know if they are outdated or I'm having a hard time implementing them to work.

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

Coding development

编码开发

First I make sure I have permissions:

首先,我确保我有权限:

  1. ACCESS_COARSE_LOCATION
  2. ACCESS_FINE_LOCATION
  3. ACCESS_MOCK_LOCATION*
  1. ACCESS_COARSE_LOCATION
  2. ACCESS_FINE_LOCATION
  3. ACCESS_MOCK_LOCATION*

Note: 1 and 2 are both checked, if they are not available I ask permission using requestPermissionsfunction. The third one is not avaiable to be asked, in fact it can only be added through AndroidManifest.xmlon debug mode.

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

I also made sure I have my APP selected in Settings > Developer options > Allow MOCK locations.

我还确保在Settings > Developer options > Allow MOCK location 中选择了我的应用程序。

After all this, I have made this function that I tried calling through OnCreate method or OnClick of a button:

毕竟,我已经创建了这个函数,我尝试通过 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();
}

If I compile and test this way I'll receive the Toast: "No location provider found!". But if I change mocLocationProvider to:

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

String mocLocationProvider = LocationManager.NETWORK_PROVIDER;

I get APP crash and in LogCat it says that crashed during this line:

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

lm.setTestProviderLocation(mocLocationProvider, mockLocation);

So I'm currently out of options and don't know how to advance.

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

回答by Hadi

you must set first:

你必须先设置:

allow mock location in setting

在设置中允许模拟位置

second set permissions:

第二组权限:

ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION ACCESS_MOCK_LOCATION

ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION ACCESS_MOCK_LOCATION

third use this method :

第三种使用此方法:

setMock(some_lat,some_lon,some accuracy);

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);}

回答by blackkara

You must set accuracy and ElapsedRealtimeNanos values

您必须设置准确度和 ElapsedRealtimeNanos 值

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

Otherwise it throws IllegalArgumentException.

否则它会抛出 IllegalArgumentException。

@throws IllegalArgumentException if the location is incomplete

如果位置不完整,@throws IllegalArgumentException

UPDATE

更新

If you mock Network provider

如果您模拟网络提供商

String mocLocationProvider = LocationManager.NETWORK_PROVIDER;

then you will receive mock location through Network provider,

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

LocationListener listener = new LocationListener(){
    ...
    void onLocationChanged(Location location){

    }
};
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, ..., listener);

And whenever you invoke setTestProviderLocation method, then onLocationChanged callback will be triggered !

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

回答by Samad

from @Blackkara's answer and comments, this is the final code, and do not forget to set the location mode to device only(GPS)

来自@Blackkara 的回答和评论,这是最终代码,不要忘记将位置模式设置为仅设备(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();