-->

Get LocationUpdates in background service continuo

2020-05-28 11:00发布

问题:

I am working on application which requires to fetch location updates continuously in background service. I have used background sticky service with which it is working. But service is not starting after boot complete even though I have added boot broadcast and have started the service there. Service starts and immediately gets killed.

Also, this is not working on Oreo. Service stops after few minutes of application gets closed and never restarts till app is relaunched.

I have gone through lot of links, blogs which suggest to use AlarmManager/JobScheduler/JobIntentService but didn't get satisfactory solution. So please suggest the working strategy/solution that can be used to continuously fetch location in background even after boot and should work on Oreo.

回答1:

Using notification, you can make your service alive. It works up to android 8.1. Below is code for background service

Note:

1) Use startForegroundService for above Build.VERSION_CODES.O

2) Use targetSdkVersion 25

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            mainActivity.startService(new Intent(getContext(), GpsServices.class));
        } else {
            mainActivity.startForegroundService(new Intent(getContext(), GpsServices.class));
        }

BackgroundGpsServices Class

public class BackgroundGpsServices extends Service implements LocationListener {
private LocationManager mLocationManager;
public final long UPDATE_INTERVAL = 500;  /* 0.5 sec */
public static final int NOTIFICATION_ID = 200;

@Override
public void onCreate() {
    sendNotification(this, false);
    startLocationUpdates();
}

private void startLocationUpdates() {
    if (!isLocationUpdateRunning) {
        isLocationUpdateRunning = true;
        mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        if (mLocationManager != null) {
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, UPDATE_INTERVAL, 0, this);
        }
    }
}

@Override
public void onLocationChanged(Location location) {
    sendNotification(BackgroundGpsServices.this, true);
    System.out.println("onLocationChanged ----- location=" + location);
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {

}

@Override
public void onProviderEnabled(String provider) {

}

@Override
public void onProviderDisabled(String provider) {
}

public static void sendNotification(Service service, boolean isUpdate) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        Intent intent = new Intent(service, MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(service, 0, intent, PendingIntent.FLAG_NO_CREATE);
        NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(service)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("INFO_NOTIFICATION_TITLE")
                .setOngoing(true)
                .setAutoCancel(false)
                .setContentText("INFO_NOTIFICATION_MESSAGE")
                .setContentIntent(pendingIntent);
        Notification notification = mNotifyBuilder.build();

        if (isUpdate) {
            NotificationManager notificationManager = (NotificationManager) service.getSystemService(NOTIFICATION_SERVICE);
            if (notificationManager != null) {
                notificationManager.notify(NOTIFICATION_ID, notification);
            }
        } else {
            service.startForeground(NOTIFICATION_ID, notification);
        }
    }
}

@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 {
        stopLocationUpdates();
        stopForeground(true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private void stopLocationUpdates() {
    isLocationUpdateRunning = false;
    if (mLocationManager != null) {
        mLocationManager.removeUpdates(this);
    }
}
}


回答2:

You can use fused location provider to get the location of the device at regular intervals. There is a direct approach to request periodic updates from the fused location provider. The accuracy of the location is determined by the providers, the location permissions you've requested, and the options you set in the location request.

Request location updates

Before requesting location updates, your app must connect to location services and make a location request. The lesson on Changing Location Settings shows you how to do this. Once a location request is in place you can start the regular updates by calling requestLocationUpdates().

Depending on the form of the request, the fused location provider either invokes the LocationCallback.onLocationChanged() callback method and passes it a list of Location objects, or issues a PendingIntent that contains the location in its extended data. The accuracy and frequency of the updates are affected by the location permissions you've requested and the options you set in the location request object.

This lesson shows you how to get the update using the LocationCallback callback approach. Call requestLocationUpdates(), passing it your instance of the LocationRequest object, and a LocationCallback. Define a startLocationUpdates() method as shown in the following code sample:

@Override
protected void onResume() {
    super.onResume();
    if (mRequestingLocationUpdates) {
        startLocationUpdates();
    }
}

private void startLocationUpdates() {
    mFusedLocationClient.requestLocationUpdates(mLocationRequest,
            mLocationCallback,
            null /* Looper */);
}

Read Official Documentation here for detailed description.

Hope this helps.