【问题标题】:Unable to clear mock location?无法清除模拟位置?
【发布时间】:2020-09-11 13:58:21
【问题描述】:

这就是我在应用中设置模拟位置的方式:

public void startMockLocation(String latitude, String longitude){

    FusedLocationProviderClient locationProvider =  new FusedLocationProviderClient(getApplicationContext());
    locationProvider.setMockMode(true);

    Location loc = new Location("gps");

    mockLocation = new Location("gps");
    mockLocation.setLatitude(Double.valueOf(latitude));
    mockLocation.setLongitude(Double.valueOf(longitude));
    mockLocation.setAltitude(loc.getAltitude());
    mockLocation.setTime(System.currentTimeMillis());

    mockLocation.setAccuracy(1f);
    mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        mockLocation.setBearingAccuracyDegrees(0.1f);
        mockLocation.setVerticalAccuracyMeters(0.1f);
        mockLocation.setSpeedAccuracyMetersPerSecond(0.01f);
    }

    locationProvider.setMockLocation(mockLocation);
}

但是,我无法使用下面的代码清除模拟位置并重新设置真实位置。我应该写什么?

public void clearMockLocation() {
    locationProvider.setMockMode(false);
}

【问题讨论】:

  • 代码很好你能在你访问当前位置的地方显示你的代码吗...?
  • 您是否获得了必要的许可?
  • @PraveenSP 我没有在任何地方访问当前位置。
  • @JavadDehban 是的,我做到了。
  • 荷兰语,如果您没有访问位置而不是您如何知道设备仍在使用模拟位置......即使将模拟设置为 false

标签: java android location android-fusedlocation


【解决方案1】:

当我看到您的代码时,您正在调用两种方法,一种是设置模拟位置,另一种是禁用它,但在其他方法中,我不确定您使用的是哪个位置提供程序对象,我希望您声明一个全局对象位置提供者并在任何地方使用它

FusedLocationProviderClient locationProvider;

public void startMockLocation(String latitude, String longitude){

    locationProvider =  new FusedLocationProviderClient(getApplicationContext());
    locationProvider.setMockMode(true);

    Location loc = new Location("gps");

    mockLocation = new Location("gps");
    mockLocation.setLatitude(Double.valueOf(latitude));
    mockLocation.setLongitude(Double.valueOf(longitude));
    mockLocation.setAltitude(loc.getAltitude());
    mockLocation.setTime(System.currentTimeMillis());

    mockLocation.setAccuracy(1f);
    mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        mockLocation.setBearingAccuracyDegrees(0.1f);
        mockLocation.setVerticalAccuracyMeters(0.1f);
        mockLocation.setSpeedAccuracyMetersPerSecond(0.01f);
    }

    locationProvider.setMockLocation(mockLocation);
}

然后在其他方法中

public void clearMockLocation() {
if(locationProvider!=null){
locationProvider.setMockMode(false);
if(mockLocation!=null){
mockLocation.setLatitude(real_latitude);
    mockLocation.setLongitude(real_longitude);
    mockLocation.setAltitude(real_altitude);
    mockLocation.setTime(System.currentTimeMillis());
    mockLocation.setAccuracy(1f);
    mockLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        mockLocation.setBearingAccuracyDegrees(0.1f);
        mockLocation.setVerticalAccuracyMeters(0.1f);
        mockLocation.setSpeedAccuracyMetersPerSecond(0.01f);
    }

    locationProvider.setMockLocation(mockLocation);
}

}

}

【讨论】:

  • 你能调试并告诉我实际发生了什么吗?
  • 这只是设置另一个模拟位置。那不是我想要的。我需要设备像往常一样返回使用当前位置。
【解决方案2】:

更新:


到目前为止,您的问题在于以下步骤:

  1. 为 Gps 设置模拟位置
  2. 转到 GoogleMaps 并查看您的模拟位置
  3. 退回您的应用并希望停止模拟

这里我给你一些技术来禁用模拟位置


方法1

使用位置管理器的 API 可以避免欺骗或伪造位置。

为此,您首先必须导入 google play services LocationServices (must visit) API:

你需要导入:

import com.google.android.gms.location.LocationServices;

而在应用级build.gradle:

implementation 'com.google.android.gms:play-services-location:17.0.0'

你的类必须实现这些接口:

public class TestMapsActivity extends FragmentActivity implements OnMapReadyCallback,
    LocationListener,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener { ...}

那么,你需要Override这些方法如:

 @Override
    public void onConnected(Bundle bundle) {

    }


    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    @Override
    public void onLocationChanged(Location location) {

    }

现在,我们可以在从providers(网络或 Gps)请求位置更新之前删除测试提供者:

LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

try {
    Log.d(TAG ,"Removing Test providers")
    locationManager .removeTestProvider(LocationManager.GPS_PROVIDER);
} catch (IllegalArgumentException error) {
    Log.d(TAG,"Got exception in removing test  provider");
}

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, locationListener);

现在,如果您查看LocationManager 的 Android 文档:

removeTestProvider() throws 
IllegalArgumentException    if no provider with the given name exists

您将从android-issue 获得更好的直觉。对于该特定线程,您可以尝试使用Criteria.ACCURACY_FINE 而不是LocationManager.GPS_PROVIDER,例如:

LocationManager locationManager = (LocationManager)context.getSystemService( Context.LOCATION_SERVICE );

Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
String locationprovider = locationManager.getBestProvider(criteria, true);

if ( locationprovider == null ) {
    Log.e(TAG, "location provider is not available.!");
    return;
}

方法2

如果上述方法仍然不适合你,你可以默默地启用/禁用模拟设置如下:

// disable mocking. 
Settings.Secure.putString(getContentResolver(),
       Settings.Secure.ALLOW_MOCK_LOCATION, "0");

你还可以得到更好的直觉herehere


方法3

还有另一种方法可以让您准确了解 GPS/网络 提供商是否已启用:

ContentResolver contentResolver = context.getContentResolver();
boolean gpsEnabled = Settings.Secure.isLocationProviderEnabled(contentResolver, LocationManager.GPS_PROVIDER);
boolean networkEnabled = Settings.Secure.isLocationProviderEnabled(contentResolver, LocationManager.NETWORK_PROVIDER);

其他步骤。


您应该按照这些步骤来clear/reset 您的模拟位置,例如:

  • 在您的设置中的开发面板中启用模拟位置。
  • 将权限添加到您的Manifest.xml

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

  • 现在再次打开 GoogleMaps,并等待 Gps 提供商接收新的实时位置。这可能有点耗时,即 (1-3 minutes)。

所以在移除提供者时,只要让 Gps 接收到一个新的位置,它就会被解析并修复。如果万一它不再工作,那么您可以进一步执行以下步骤:

进入应用设置,清除应用缓存并重新启动移动 设备

我希望它能很好地工作。您还可以访问这些参考资料以获得更好的直觉:

【讨论】:

  • 感谢您的回答。该代码并不总是有效,因为我的应用程序经常因以下错误而崩溃:java.lang.IllegalArgumentException: Provider "gps" unknown
  • 我已经更新了我的问题。如果它仍然无法正常工作,那么几乎可以肯定您的device/emulator 上没有启用 GPS 提供程序。 它必须具有此功能才能接收模拟位置
  • @Dutch 我已经使用不同的技术更新了我的答案,其中包含最可能的场景。请重新访问并告诉我,我该如何进一步帮助您?
  • 按照方法1后我得到error Cannot resolve symbol locationListener
  • @Dutch 我改进了方法 1,以便您可以轻松地包含位置侦听器 API。它将解决您的错误。我在最近的更新中给出了一个参考,让你有更好的直觉。请必访
猜你喜欢
  • 1970-01-01
  • 2016-02-28
  • 2011-12-12
  • 1970-01-01
  • 2014-11-08
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多