Search code examples
androidgpsandroid-fusedlocation

Android fused location api not providing consistent updates with screen off


I have some code that runs multiple times per second in my app. I'm trying to get my location in every cycle. I am using the following:

Location myLastPos = LocationServices.FusedLocationApi.getLastLocation(googleApiClient)

My app also runs in the background using a PARTIAL_WAKE_LOCK. With the screen on everything seems OK. When I turn the screen off my app still runs normally but I no longer get location updates consistently. It appears that I get updates much less frequently (often minutes in between updates). I'm checking the timestamp of the location using:

myLastPos.getElapsedRealtimeNanos()

I also found that even when the screen is on I get some strange results. Sometimes I get a few milliseconds between updates, other times I get a few seconds. This is all very concerning. Can someone either help me use FusedLocationApi properly or suggest an alternative. All I really want is to poll the gps directly for lat/long a few times a second without google libraries getting in the way.


Solution

  • The getLastLocation() method just gets the last known location that the device happens to know. The "last known location" here means exactly that: It may not be up-to-date. Locations do come with a time stamp which could be used to asses if the location might still be relevant.

    The device doesn't determine its location on its own, but only when some application request the location. So your app is now dependent on other applications requesting location updates.

    If you need updates every few seconds, then request regular location updates yourself.

    Android documentation recommends the FusedLocationProvider, but the LocationManager is also a perfectly valid option, if there's any reason to avoid the Google Play services.

    The basic idea is to first request location updates:

    // Using LocationManager as an example.
    mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    // Using GPS, requesting location updates as soon as available and even for
    // the smallest changes. Here 'this' refers to our LocationListener 
    // implementation.
    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
    

    The updates are then received by a listener:

    @Override
        public void onLocationChanged(Location location) {
            // We received a location update.
            // Copy the value from the method parameter to our
            // class member variable.
            mLocation = location;
        }
    

    And when you no longer need the updates you should cancel the request:

    mLocationManager.removeUpdates(this);
    

    The approach is very similar for the FusedLocationProvider.