How to check for Mock Location in Android Marshmallow?
Asked Answered
G

6

13

How to detect if the location is triggered with Mock Location in Android Marshmallow?

Previously, I used Settings.Secure.ALLOW_MOCK_LOCATION

But, in API level 23, this has been deprecated.

I want to check if the trigger is with Fake location or original GPS ?

Now, what is the alternative to check if Mock Location is enabled or not Android Marshmallow?

Glass answered 19/9, 2015 at 12:59 Comment(0)
H
14

If you are using FusedLocationProviderApi and have set mock location using setMockLocation(mGoogleApiClient, fakeLocation); in the callback/pendingIntentCallback the returned Location object contains KEY_MOCK_LOCATION extra, a boolean that indicates that received object is mock.

@Override

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

}
Header answered 27/9, 2015 at 13:17 Comment(4)
Any reason why you can't just use the isFromMockProvider() method's result? Seems like the documentation is pretty clear that it should return true if it is a mock location.Cnemis
@NormanH I am working on old code which uses Location Manager instead. For Marshmallow, I used location.isFromMockProvider() . Once I start FakeGPS isFromMockProvider() returns true. Hereon if I start or even stop, the isFromMockProvider() always returns true. Looks like FakeGPS overrides the location of Location Mnaager and even after stopping FakeGPS, the location manager is not starting again. Any suggestions what might be going wrong here?Proud
It seems isFromMockProvider might get you false negative, according to this article: klaasnotfound.com/2016/05/27/… . I wonder if it got fixed.Dissatisfy
From my experience, isFromMockProvider() and the KEY_MOCK_LOCATION extra always contain the exact same info. Also, as stated in the comment above, both can be wrong (i.e. a mock is not labeled as such) from time to time. So far this hasn't been fixed. See here and my answer below for more info... To reliably suppress mock locations on non-rooted devices with API 15+ you may use this class I have written.Above
A
13

The accepted answer is a working solution, however, I would like to add some points for the sake of completeness.

The best built-in way to detect a mock location (not just since Marshmallow, but since API 18+) is to use Location.isFromMockProvider(), as stated in other answers and comments.

I extensively experimented with mock locations on different devices and OS versions and came to the following conclusion:

  • The KEY_MOCK_LOCATION extra bears the exact same information as .isFromMockProvider(), i.e. .isFromMockProvider() will return true when the extra is present and false when it isn't. In other words, it provides no added value and is just a more complicated way of finding out whether an individual location was labeled as a mock by its provider. See here for more info.
    So I would definitely recommend using .isFromMockProvider().

  • Both the extra and the getter can sporadically return false negatives, i.e. the location in question is a mock but not labeled as such. This is obviously really bad for certain use cases. I have written a detailed blog post on this subject if you want to learn more.

After struggling with Android location (and the mock labeling problem) for quite some time I published the LocationAssistant, a utility class that will reliably reject mock locations on non-rooted devices with API 15+. It also unburdens you from most of the FusedLocationProvider boilerplate. Maybe you'll find it useful for your next location-aware app project.

Above answered 8/1, 2017 at 21:25 Comment(0)
I
8

This answer didn't seem to be work for me. extras.getBoolean(FusedLocationProviderApi.KEY_MOCK_LOCATION, false) always returned false.

However, I did this:

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

and I started getting the correct results.

Instantaneity answered 9/12, 2015 at 21:55 Comment(0)
M
3

In marshmallow you can check mock_location by using the AppOpsManager.

Similar answer here: How to read selected mock location app in Android M - API 23

Miley answered 11/10, 2015 at 15:45 Comment(0)
G
1
fun isLocationMocked(location: Location): Boolean {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        location.isMock
    } else {
        location.isFromMockProvider
    }
}

This function checks if the location is mocked using isMock method for API 31 and above, and for lower versions it uses the isFromMockProvider method.

Remember, similar to isFromMockProvider, the isMock method is also not foolproof against sophisticated location spoofing techniques.

Gynecocracy answered 22/6, 2023 at 14:0 Comment(0)
K
0

This not working always return false also FusedLocationProviderApi is deprecated.

extras.getBoolean(FusedLocationProviderApi.KEY_MOCK_LOCATION, false)

Below approach is working for me getting proper detection of mock location

@Override
public void onLocationChanged (Location location){
    boolean isMockLocation = location.isFromMockProvider();
}
Kingston answered 9/10, 2021 at 12:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.