无法清除模拟位置?

Posted

技术标签:

【中文标题】无法清除模拟位置?【英文标题】: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 【参考方案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】:

更新:


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

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

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


方法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");

你还可以得到更好的直觉here和here。


方法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 接收到一个新的位置,它就会被解析并修复。如果万一它不再工作,那么您可以进一步执行以下步骤:

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

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

Android-mock-location-on-device Remove-mock-location

【讨论】:

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

以上是关于无法清除模拟位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何在每次测试之前重置或清除 ApolloProvider 的 useQuery 模拟?

JavaScript无法刷新 - 必须清除缓存

清除 MHLazyTableImages 的缓存

iOS清除缓存,模拟器有效,但在真iPhone时无效

如何清除 Jest 模拟实现以进行下一次测试?

模拟器“模拟内存警告”事件清除生成分析内存增长的意义