Search code examples
androidandroid-locationandroid-intentserviceandroid-googleapiclient

requestLocationUpdates five times started from IntentService


My control flow is in an IntentService (triggered by a GcmListenerService) and should now get the location of the user. As

LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient)

might return null, I should request some location updates. I assume with every update the location is more accurate than the one before because of GPS mechanics. I suppose five measurements/updates should be enough for an accurate location. How can I implement that logic in an IntentService? The class implements the listener interfaces:

public class LocationIntentService extends IntentService
 implements GoogleApiClient.ConnectionCallbacks,
 GoogleApiClient.OnConnectionFailedListener,
 LocationListener

This way I could use a counter in public void onLocationChanged(Location location) and call LocationServices.FusedLocationApi.removeLocationUpdates() after five updates. However, I'm not sure if I can trust Android that the same IntentService lives that long and is not removed by the garbage collector as soon as onHandleIntent is done.

This is the complete code I'm using so far without the logic to collect only five updates:

public class LocationIntentService extends IntentService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private GoogleApiClient mGoogleApiClient;

    public LocationIntentService() {
        super("LocationIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        mGoogleApiClient = new GoogleApiClient.Builder(getBaseContext())
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        System.out.println(result.toString());
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        LocationRequest mLocationRequest = LocationRequest.create();
        mLocationRequest.setInterval(500);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }

    @Override
    public void onConnectionSuspended(int cause) {
    }

    private void displayLocation(Location location) {
        System.out.println(location.toString());
        DbHandler dbHandler = new DbHandler(getBaseContext());
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        double altitude = location.getAltitude();
        float speed = location.getSpeed();
        long time = location.getTime();
        float accuracy = location.getAccuracy();
        PersistedLocation persistedLocation = new PersistedLocation(time, latitude, longitude, altitude, accuracy, speed);
        dbHandler.insertLocation(persistedLocation);
    }

    @Override
    public void onLocationChanged(Location location) {
        displayLocation(location);
    }
}

Solution

  • I managed to accomplish this with setNumUpdates(int i) and setExpirationDuration(long l).

    @Override
    public void onConnected(Bundle connectionHint) {
        LocationRequest mLocationRequest = LocationRequest.create();
        mLocationRequest.setInterval(500);
        mLocationRequest.setNumUpdates(5);
        mLocationRequest.setExpirationDuration(10000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
        }
    }