Android background image location update does not occur when screen is off

We are working on a mobile tracking application. For location updates, the floating-location API is used with high precision as a priority.

A location update is required even if the screen is off. So we use background Service. The background Servicealso gets partial WakeLock, so the device does not go into sleep mode. In the background, Servicewe request location updates with a pending update Service.

The problem is that we only get location updates when the screen is on. As soon as the screen turns off, update updates will stop. There is also an Threadexecutable Servicethat does not kill at any point.

Making a location request again when the screen is off using BroadcastReceiveralso does not work.

Here is the background of Serviceclass ( RouteExecution):

private static final String TAG = "RouteExecution";

private static RouteExecution routeExecution = null;

private static GoogleApiClient mGoogleApiClient;
private static PendingIntent pendingIntent = null;
private PowerManager.WakeLock waitLock;
/**
 * Creates an IntentService.  Invoked by your subclass constructor.
 */
public RouteExecution() {
    super(TAG);

    RouteExecution.routeExecution = this;
}

@Override
public void onCreate() {
    super.onCreate();

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

    mGoogleApiClient.connect();

    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new PowerButtonReceiver();
    registerReceiver(mReceiver, filter);

    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    waitLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    waitLock.acquire();
}

@Override
protected void onHandleIntent(Intent intent) {

    if (LocationResult.hasResult(intent)) {

        LocationResult locationResult = LocationResult.extractResult(intent);
        Location location = locationResult.getLastLocation();

        GPSLocation gpsLocation = new GPSLocation(location);

        Log.d(TAG, "Location Accuracy: " + location.getAccuracy() + " "
                + " has: " + location.hasAccuracy() + " Provider: " + location.getProvider()
                + " long: " + location.getLongitude() + " lat: " + location.getLatitude());
    }
}



public boolean checkLocationPermission() {

    if (ActivityCompat.checkSelfPermission(routeExecution, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
            && ActivityCompat.checkSelfPermission(routeExecution, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return false;
    }

    return true;
}

public void createLocationListener() {

    if (!this.checkLocationPermission()) {
        return;
    }

    LocationRequest mLocationRequest = LocationRequest.create();
    mLocationRequest.setInterval(5000);
    mLocationRequest.setFastestInterval(5000);
    mLocationRequest.setSmallestDisplacement(0);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    PendingResult<Status> statusPendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
            mLocationRequest, pendingIntent);
}

@Override
public void onConnected(@Nullable Bundle bundle) {

    Log.d(TAG, mGoogleApiClient.isConnected() + "   On Connected");
    synchronized (this) {

            createLocationListener();
    }
}


public static GoogleApiClient getmGoogleApiClient() {
    return mGoogleApiClient;
}

@Override
public void onDestroy() {
    super.onDestroy();


    waitLock.release();
    mGoogleApiClient.disconnect();
}

public static RouteExecution getRouteExecution() {
    return routeExecution;
}

public static void setPendingIntent(PendingIntent pendingIntent) {
    RouteExecution.pendingIntent = pendingIntent;
}

Servicestarts using AlarmManager. Here is the extract:

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent updateServiceIntent = new Intent(context, RouteExecution.class);
PendingIntent pendingUpdateIntent = PendingIntent.getService(context, 0, updateServiceIntent, 0);
RouteExecution.setPendingIntent(pendingUpdateIntent);
alarmManager.set(AlarmManager.RTC_WAKEUP, 50000, pendingUpdateIntent);

BroadcastReceiver:

public class PowerButtonReceiver extends BroadcastReceiver {
    private static final String TAG = "PowerButton";

    @Override
    public void onReceive(Context context, Intent intent) {

        Log.d(TAG, "Power Button");
        if (RouteExecution.getRouteExecution() != null) {
            RouteExecution.getRouteExecution().createLocationListener();
        }
    }
}

How to keep location updates even if the screen is off.

Thanks for the help.

+4
source share
1 answer

, WakeLock Service . , .

PendingIntent.getBroadcast() PendingIntent.getService(), a WakeLock onReceive() Service .

WakeLock onReceive(), Service WakeLock Service,

WakefulBroadcastReceiver, , .

AlarmManager.set() Marshmallow.

, , , Doze.

setAndAllowWhileIdle() set() API 23 +.

0

Source: https://habr.com/ru/post/1653755/


All Articles