Android LocationClient.getLastLocation() returns o

2020-03-24 16:32发布

问题:

I've been using the fused location provider since its release and I am pretty happy with it (way better than the old system). But I ran into a peculiar problem when using geofencing in combination with LocationClient.lastKnownLocation(). The setup is as follows:

I drop several geofences around some home location (with increasing ranges). When I get the intent that a fence is crossed I retrieve the last known location from LocationClient and work with it. Apart from than I also registered for regular location updates with update mode PRIORITY_BALANCED_POWER_ACCURACY.

Most of the times this works perfectly fine, but sometimes this happens:

Time 000 s - (Lat,Lon,Accuracy) = (48.127316,11.5855167,683.0)

Time 120 s - (Lat,Lon,Accuracy) = (48.1260497,11.5731745,31.823)

Time 300 s - (Lat,Lon,Accuracy) = (48.1217455,11.5641666,143.81)

Time 420 s - (Lat,Lon,Accuracy) = (48.1189942,11.559061,36.0)

Time 600s - (Lat,Lon,Accuracy) = (48.127316,11.5855167,683.0)

Notice that all these locations are retrieved by getLastKnownLocation(). What seems fishy here is that the first and the last location are identical (even in the other attributes), to be more specific:

* intent at time 0: *

component: ComponentInfo{package.Class}
key [location]: Location[mProvider=fused,mTime=1373524391934,mLatitude=48.127316,mLongitude=11.5855167,mHasAltitude=false,mAltitude=0.0,mHasSpeed=false,mSpeed=0.0,mHasBearing=false,mBearing=0.0,mHasAccuracy=true,mAccuracy=683.0,mExtras=Bundle[mParcelledData.dataSize=352]]

* intent at time 600: *

component: ComponentInfo{package.Class}
key [location]: Location[mProvider=fused,mTime=1373524994871,mLatitude=48.127316,mLongitude=11.5855167,mHasAltitude=false,mAltitude=0.0,mHasSpeed=false,mSpeed=0.0,mHasBearing=false,mBearing=0.0,mHasAccuracy=true,mAccuracy=683.0,mExtras=Bundle[mParcelledData.dataSize=352]]

* note the ~600 s difference in the timestamp * 

I do not understand how this can happen, as there have been locations in between that were both more recent and more accurate. Also the new timestamp on an old location makes me curious... apparently similar things happened when using the old API, but this new location provider is just called fused, so I can not distinguish GPS from WPS from sensors... If it is the cell tower switching problem (outlined in the linked question concerning the old API) then why would the phone connect to a "far away" tower if it has seen closer towers?

Why is this happening?

回答1:

The first and last points were gotten using cell triangulation. The error/accuracy is typical of cell-based location, and it looks like the Google power saving logic decided that switching to cell would be OK, even as you say its recent history included points much closer.



回答2:

Aw, SHUCKS! I got this too today... And I moved to the new Google Play Services location precisely to AVOID this... And I was so thrilled up until just now when I got it too. You may or may not know that the old one had these kind of problems, and it was a pain.

There are lots of threads regarding this, including one of my own :(

Why is locationmanager returning old location fixes with new gettime-timestamp?

I guess the only thing to do is avoid using cached location...



回答3:

Instead of polling, one can work around one or more sources of inaccuracy using this subscription mechanism.

LocationListener locListener = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        if (location == null)
            return;
        // process these:
        // location.getLatitude();
        // location.getLongitude();
        // location.getAccuracy();
        ...
    }
    ... 
}

((LocationManager) getSystemService(Context.LOCATION_SERVICE)
        .requestLocationUpdates(LocationManager.GPS_PROVIDER,
                minTimeMilliSec,
                minDistanceMeters,
                locListener));