检测模拟位置不起作用 (Android)
Detecting Mock Location Not Working (Android)
我正在尝试设置一些保护措施,以防止有人使用模拟位置来操纵我的应用程序。我意识到不可能 100% 阻止...我只是尽力而为。
该应用在其主要 activity 中使用 Google 定位服务(播放服务的一部分)。
onLocationChanged() 方法是:
public void onLocationChanged(Location location) {
this.mCurrentLocation = location;
if (Build.VERSION.SDK_INT > 17 && mCurrentLocation.isFromMockProvider()) {
Log.i(TAG, "QQ Location is MOCK");
// TODO: add code to stop app
// otherwise, currently, location will never be updated and app will never start
} else {
Double LAT = mCurrentLocation.getLatitude();
Double LON = mCurrentLocation.getLongitude();
if ((LAT.doubleValue() > 33.309171) || (LAT.doubleValue() < 33.226442) || (LON.doubleValue() < -90.790165) || (LON.doubleValue() > -90.707081)) {
buildAlertMessageOutOfBounds();
} else if (waiting4FirstLocationUpdate) {
Log.i(TAG, "YYY onLocationChanged() determines this is the FIRST update.");
waiting4FirstLocationUpdate = false;
setContentView(R.layout.activity_main);
startDisplayingLists();
}
}
}
位置服务完美运行,总体而言,应用程序一切正常,但是当我 运行 应用程序在带有 Android Studio 的模拟器中时(Nexus One API 23) ,并且我使用扩展控件(模拟)设置了位置,该应用程序继续正常工作,因此情况似乎是:
if (Build.VERSION.SDK_INT > 17 && mCurrentLocation.isFromMockProvider())
正在返回 false。
这对我来说没有任何意义。有谁知道为什么会这样?
谢谢!
简短的回答:.isFromMockProvider 是不可靠的。 一些虚假的位置没有被正确检测到。
我花了很多时间研究这个并写了一篇关于它的 detailed blog post。
我还花时间寻找一种解决方案,以可靠地抑制所有 recent/relevant Android 版本的模拟位置,并制作了一个名为 LocationAssistant 的实用程序 class,它完成任务。
简而言之(使用前面提到的 LocationAssistant):
在您的清单中设置权限并在您的 gradle 文件中设置 Google Play 服务。
将文件 LocationAssistant.java 复制到您的项目。
在 Activity 的 onCreate()
方法中,用所需的参数实例化一个 LocationAssistant
。例如,要大约每 5 秒接收一次高精度位置更新 并拒绝模拟位置 ,请调用 new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, false)
。最后一个参数指定不应允许模拟位置。
Start/stop 助手与您的 Activity 并通知它 permission/location 设置更改(详情请参阅 documentation)。
享受 onNewLocationAvailable(Location location)
中的位置更新。如果您选择拒绝模拟位置,则仅使用非模拟位置调用回调。
还有一些方法可以实现,但基本上就是这些了。显然,有一些方法可以绕过 root 设备的模拟提供程序检测,但在库存的非 root 设备上,拒绝应该可靠地工作。
我正在尝试设置一些保护措施,以防止有人使用模拟位置来操纵我的应用程序。我意识到不可能 100% 阻止...我只是尽力而为。
该应用在其主要 activity 中使用 Google 定位服务(播放服务的一部分)。
onLocationChanged() 方法是:
public void onLocationChanged(Location location) {
this.mCurrentLocation = location;
if (Build.VERSION.SDK_INT > 17 && mCurrentLocation.isFromMockProvider()) {
Log.i(TAG, "QQ Location is MOCK");
// TODO: add code to stop app
// otherwise, currently, location will never be updated and app will never start
} else {
Double LAT = mCurrentLocation.getLatitude();
Double LON = mCurrentLocation.getLongitude();
if ((LAT.doubleValue() > 33.309171) || (LAT.doubleValue() < 33.226442) || (LON.doubleValue() < -90.790165) || (LON.doubleValue() > -90.707081)) {
buildAlertMessageOutOfBounds();
} else if (waiting4FirstLocationUpdate) {
Log.i(TAG, "YYY onLocationChanged() determines this is the FIRST update.");
waiting4FirstLocationUpdate = false;
setContentView(R.layout.activity_main);
startDisplayingLists();
}
}
}
位置服务完美运行,总体而言,应用程序一切正常,但是当我 运行 应用程序在带有 Android Studio 的模拟器中时(Nexus One API 23) ,并且我使用扩展控件(模拟)设置了位置,该应用程序继续正常工作,因此情况似乎是:
if (Build.VERSION.SDK_INT > 17 && mCurrentLocation.isFromMockProvider())
正在返回 false。
这对我来说没有任何意义。有谁知道为什么会这样?
谢谢!
简短的回答:.isFromMockProvider 是不可靠的。 一些虚假的位置没有被正确检测到。 我花了很多时间研究这个并写了一篇关于它的 detailed blog post。
我还花时间寻找一种解决方案,以可靠地抑制所有 recent/relevant Android 版本的模拟位置,并制作了一个名为 LocationAssistant 的实用程序 class,它完成任务。
简而言之(使用前面提到的 LocationAssistant):
在您的清单中设置权限并在您的 gradle 文件中设置 Google Play 服务。
将文件 LocationAssistant.java 复制到您的项目。
在 Activity 的
onCreate()
方法中,用所需的参数实例化一个LocationAssistant
。例如,要大约每 5 秒接收一次高精度位置更新 并拒绝模拟位置 ,请调用new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, false)
。最后一个参数指定不应允许模拟位置。Start/stop 助手与您的 Activity 并通知它 permission/location 设置更改(详情请参阅 documentation)。
享受
onNewLocationAvailable(Location location)
中的位置更新。如果您选择拒绝模拟位置,则仅使用非模拟位置调用回调。
还有一些方法可以实现,但基本上就是这些了。显然,有一些方法可以绕过 root 设备的模拟提供程序检测,但在库存的非 root 设备上,拒绝应该可靠地工作。