如何检查 Android Marshmallow 中的模拟位置?

How to check for Mock Location in Android Marshmallow?

如何在Android Marshmallow中检测位置是否被Mock Location触发?

之前我用的是Settings.Secure.ALLOW_MOCK_LOCATION

但是,在 API 级别 23 中,这已被弃用。

我想检查触发器是假位置还是原始 GPS?

现在,有什么方法可以检查 Mock Location 是否启用 Android Marshmallow

如果您正在使用 FusedLocationProviderApi 并在 callback/pendingIntentCallback 中使用 setMockLocation(mGoogleApiClient, fakeLocation); 设置了模拟位置,则返回的 Location 对象包含 KEY_MOCK_LOCATION 额外的布尔值这表明接收到的对象是模拟的。

@Override

public void onLocationChanged (Location location){    
   Bundle extras = location.getExtras();
   boolean isMockLocation = extras != null && extras.getBoolean(FusedLocationProviderApi.KEY_MOCK_LOCATION, false);

}

在 marshmallow 中,您可以使用 AppOpsManager 检查 mock_location。

这里有类似的答案:How to read selected mock location app in Android M - API 23

似乎对我不起作用。 extras.getBoolean(FusedLocationProviderApi.KEY_MOCK_LOCATION, false) 总是返回 false。

然而,我这样做了:

@Override
public void onLocationChanged (Location location){
    boolean isMockLocation = location.isFromMockProvider();
}

我开始得到正确的结果。

接受的答案是一个可行的解决方案,但是,为了完整起见,我想补充一些要点。

检测模拟位置的最佳内置方法(不仅自 Marshmallow 以来,而且自 API 18+ 以来)是使用 Location.isFromMockProvider(),如其他答案和评论。

我在不同设备和 OS 版本上对模拟位置进行了广泛试验,得出以下结论:

  • KEY_MOCK_LOCATION extra 包含与 .isFromMockProvider() 完全相同的信息,即 .isFromMockProvider() 将 return true 当 extra 是存在,false 不存在。换句话说,它不提供任何附加值,只是一种更复杂的方法,用于查明某个位置是否被其提供者标记为模拟位置。有关详细信息,请参阅 here
    所以我肯定会推荐使用 .isFromMockProvider().

  • extra 和 getter 偶尔会 return 假阴性 ,即有问题的位置是模拟但不是标记为这样。对于某些用例来说,这显然非常糟糕。如果你想了解更多,我已经写了一篇关于这个主题的详细文章blog post

在与 Android 位置(和模拟标签问题)斗争了很长一段时间后,我发布了 LocationAssistant,一个实用程序 class,它将可靠地拒绝非模拟位置API 15+ 的 root 设备。它还使您从大多数 FusedLocationProvider 样板文件中解脱出来。也许您会发现它对您的下一个位置感知应用程序项目很有用。

这并不总是有效 return false 并且 FusedLocationProviderApi 已被 弃用

extras.getBoolean(FusedLocationProviderApi.KEY_MOCK_LOCATION, false)

下面的方法对我来说很有效,可以正确检测模拟位置

@Override
public void onLocationChanged (Location location){
    boolean isMockLocation = location.isFromMockProvider();
}