无法清除模拟位置?
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。它将解决您的错误。我在最近的更新中给出了一个参考,让你有更好的直觉。请必访。以上是关于无法清除模拟位置?的主要内容,如果未能解决你的问题,请参考以下文章