Since API 18 release, Location object has the method isFromMockProvider to check whether the location is from MockProvider.
public static boolean isMockLocation(Location location) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && location != null && location.isFromMockProvider();
}
On API 17 and below, mock locations are detected using Settings.Secure.
public static Boolean isMockLocationEnabled(Context context) {
return !Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
}
The general pattern with mock locations is that bearing, speed, accuracy, altitude and time interval (between consecutive data points) are hard-coded values. But some times isFromMockProvider is unreliable for some location means they are not tagged as mock location. But these locations have much poorer accuracy than the other mock location readings. Most of the Fake GPS send all location with fixed accuracy. But when you disable the Fake GPS, the untagged location might show up because of the outcome of fusion logic of FusedLocation API.
So what you can do to detect these locations
- Keep the most recent detected mock location.
- Calculate the distance between last mock location and current untagged location.
- If calculated distance is less than 1 KM then reject it.
- Remove last stored mock location if you have received atleast 10 good location.
This approach would work most of the time, but sometime this solution still be fooled.
Code is copied from this blog .