检测模拟位置不起作用 (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):

  1. 在您的清单中设置权限并在您的 gradle 文件中设置 Google Play 服务。

  2. 将文件 LocationAssistant.java 复制到您的项目。

  3. 在 Activity 的 onCreate() 方法中,用所需的参数实例化一个 LocationAssistant。例如,要大约每 5 秒接收一次高精度位置更新 并拒绝模拟位置 ,请调用 new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, false)。最后一个参数指定不应允许模拟位置。

  4. Start/stop 助手与您的 Activity 并通知它 permission/location 设置更改(详情请参阅 documentation)。

  5. 享受 onNewLocationAvailable(Location location) 中的位置更新。如果您选择拒绝模拟位置,则仅使用非模拟位置调用回调。

还有一些方法可以实现,但基本上就是这些了。显然,有一些方法可以绕过 root 设备的模拟提供程序检测,但在库存的非 root 设备上,拒绝应该可靠地工作。