First of all, I'm a developer of SpeedView, a GPS speedometer for Android, so you can trust me when I say that we tried every possible solution to this problem, all with the same negative result. Let's start by reiterating what doesn't work:
- onStatusChanged() doesn't get called on Eclair and Froyo. It does get called on 1.6 though.
- Simply counting all available satellites is, of course, useless.
- Checking if any of the satellites returns true for usedInFix() isn't very helpful also. The system apparently loses the fix but still continue to report that there are several sats that are used in it.
So, the only working solution we have, and the one we actually use in our application, is the following. Let's say we have this simple class that implements the GpsStatus.Listener:
private class MyGPSListener implements GpsStatus.Listener {
public void onGpsStatusChanged(int event) {
switch (event) {
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
if (mLastLocation != null)
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;
if (isGPSFix) { // A fix has been acquired.
// Do something.
} else { // The fix has been lost.
// Do something.
}
break;
case GpsStatus.GPS_EVENT_FIRST_FIX:
// Do something.
isGPSFix = true;
break;
}
}
}
OK, now in onLocationChanged() you should add the following:
@Override
public void onLocationChanged(Location location) {
if (location == null) return;
mLastLocationMillis = SystemClock.elapsedRealtime();
// Do something.
mLastLocation = location;
}
And that's it. Basically, this is the line that does it all:
isGPSFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000;
You can tweak the milliseconds value of course, but I would suggest to set it around 3-5 seconds.
This actually works and though I haven't seen the source code that implements the standard GPS icon, this comes close to replicating its behavior. It could even outdo it lol. Hope this helps someone.