In Oreo (8.0.0+) (API 26+), How to get a location services update when the app is in the background or kill

ketan dhopeshwarkar picture ketan dhopeshwarkar · Jan 15, 2018 · Viewed 15k times · Source

In Android O (8.0.0+) (API 26+), How to get a location services update when the app is in the background or kill. In "Strava" Android App (Available on Play Store), location services run properly when the app is in the background or kill. I need to build same functionality in my app. Whenever I start service using

startService(new Intent(this, GpsServices.class));

Then the onDestroy method is called after 10 sec when an app is an idle mode (the app is in the background or kill). Below is my code.

public class GpsServices extends Service implements LocationListener, Listener {

    @Override
    public void onCreate() {
        mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        if (mLocationManager != null) {
            mLocationManager.addGpsStatusListener(this);
        }
        if (mLocationManager != null) {
            mLocationManager.requestLocationUpdates(
                LocationManager.GPS_PROVIDER,
                500,
                0,
                this);
        }    
    }

    public void onLocationChanged(Location location) {
        System.out.println("location = [" + location + "]");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // If we get killed, after returning from here, restart
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // We don't provide binding, so return null
        return null;
    }

    /* Remove the locationlistener updates when Services is stopped */
    @Override
    public void onDestroy() {
        try {
            mLocationManager.removeUpdates(this);
            mLocationManager.removeGpsStatusListener(this);
            stopForeground(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Any help would be appreciated.

Answer

Amrut Bidri picture Amrut Bidri · Jan 16, 2018

You can try one of below two options or a combination of both, which have solved my problems when I have faced them.

Option 1

For location update to continue running in the background, you must use LocationServices API with FusedLocationProviderClient as described here and here in docs or here in CODEPATH.

Option 2

If you would have read the Android Oreo 8.0 Documentation properly somewhere in here, you would have landed on this solution.

Step 1: Make sure you start a service as a foreground service as given in below code

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {

            mainActivity.startService(new Intent(getContext(), GpsServices.class));
            mainActivity.startService(new Intent(getContext(), BluetoothService.class));
            mainActivity.startService(new Intent(getContext(), BackgroundApiService.class));
        }
        else {
            mainActivity.startForegroundService(new Intent(getContext(), GpsServices.class));
            mainActivity.startForegroundService(new Intent(getContext(), BluetoothService.class));
            mainActivity.startForegroundService(new Intent(getContext(), BackgroundApiService.class));
        }

Step 2: Use notification to show that your service is running. Add below line of code in onCreate method of service.

@Override
public void onCreate() {
    ...
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForeground(NOTIFICATION_ID, notification);
    }
    ...
}

Step 3: Remove the notification when the service is stopped or destroyed.

@Override
public void onDestroy() {
    ...
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
          stopForeground(true); //true will remove notification
    }
    ...
}

One problem with Option 2 is that it will keep showing the notification until your GpsService is running on all devices running on Android Oreo 8.0.

I'm sure that both these options will work even when the app is in the background or in kill state.

I hope this solution might solve your problem.