Stumbled upon this thread a couple years later. In 2016, most Android devices will have API level >= 18 and should thus rely on Location.isFromMockProvider() as pointed out by Fernando.
I extensively experimented with fake/mock locations on different Android devices and distros. Unfortunately .isFromMockProvider() is not 100% reliable. Every once in a while, a fake location will not be labeled as mock. This seems to be due to some erroneous internal fusion logic in the Google Location API.
I wrote a detailed blog post about this, if you want to learn more. To summarize, if you subscribe to location updates from the Location API, then switch on a fake GPS app and print the result of each Location.toString() to the console, you will see something like this:
Notice how, in the stream of location updates, one location has the same coordinates as the others, but is not flagged as a mock and has a much poorer location accuracy.
To remedy this problem, I wrote a utility class that will reliably suppress Mock locations across all modern Android versions (API level 15 and up):
LocationAssistant - Hassle-free location updates on Android
Basically, it "distrusts" non-mock locations that are within 1km of the last known mock location and also labels them as a mock. It does this until a significant number of non-mock locations have arrived.
The LocationAssistant can not only reject mock locations, but also unburdens you from most of the hassle of setting up and subscribing to location updates.
To receive only real location updates (i.e. suppress mocks), use it as follows:
public class MyActivity extends Activity implements LocationAssistant.Listener {
private LocationAssistant assistant;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// You can specify a different accuracy and interval here.
// The last parameter (allowMockLocations) must be 'false' to suppress mock locations.
assistant = new LocationAssistant(this, this, LocationAssistant.Accuracy.HIGH, 5000, false);
}
@Override
protected void onResume() {
super.onResume();
assistant.start();
}
@Override
protected void onPause() {
assistant.stop();
super.onPause();
}
@Override
public void onNewLocationAvailable(Location location) {
// No mock locations arriving here
}
...
}
onNewLocationAvailable()
will now only be invoked with real location info. There are some more listener methods you need to implement, but in the context of your question (how to prevent GPS spoofing) this is basically it.
Of course, with a rooted OS you can still find ways of spoofing location info that are impossible for normal apps to detect.