Постоянно получать LocationUpdates в фоновом режиме

Я работаю над приложением, которое требует непрерывной загрузки обновлений местоположения в фоновом режиме. Я использовал фоновый липкий сервис, с которым он работает. Но служба не запускается после завершения загрузки, хотя я добавил загрузочную трансляцию и запустил службу там. Служба запускается и сразу же убивается.

Кроме того, это не работает на Oreo. Служба останавливается через несколько минут после закрытия приложения и никогда не перезапускается до перезапуска приложения.

Я просмотрел множество ссылок, блогов, которые предлагают использовать AlarmManager/JobScheduler/JobIntentService, но не нашел удовлетворительного решения. Поэтому, пожалуйста, предложите работающую стратегию/решение, которое можно использовать для непрерывной выборки местоположения в фоновом режиме даже после загрузки и должно работать на Oreo.


person Virat18    schedule 05.07.2018    source источник
comment
Пожалуйста, обратитесь к этому вопросу, я надеюсь, что он решит ваш запрос... stackoverflow.com/questions/47090007/   -  person vikas singh    schedule 05.07.2018


Ответы (2)


Используя уведомление, вы можете оживить свой сервис. Работает до андроид 8.1. Ниже приведен код для фоновой службы

Примечание:

1) Используйте startForegroundService для выше Build.VERSION_CODES.O

2) Используйте 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

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);
    }
}
}
person KetanD    schedule 05.07.2018
comment
не могли бы вы объяснить, что делает этот код в уведомлении об отправке? Я попробовал это решение. Выбор местоположения в фоновом режиме работает. Но я не вижу никаких уведомлений, отображаемых моим приложением. Я вижу уведомление, отображаемое системой «2 приложения используют батарею», а ниже имя моего приложения. - person Virat18; 09.07.2018
comment
@Virat18 Используйте compileSdkVersion 26 и targetSdkVersion 25, тогда вы сможете увидеть уведомление - person KetanD; 19.07.2018

Вы можете использовать поставщик объединенного местоположения, чтобы узнать местоположение устройства. через равные промежутки времени. Существует прямой подход к запросу периодических обновлений от поставщика объединенных местоположений. Точность определения местоположения определяется провайдерами, запрошенными вами разрешениями на определение местоположения и параметрами, которые вы задали в запросе на определение местоположения.

Запрос обновлений местоположения

Прежде чем запрашивать обновления местоположения, ваше приложение должно подключиться к службам определения местоположения и сделать запрос местоположения. В уроке «Изменение настроек местоположения» показано, как это сделать. После того, как запрос местоположения будет готов, вы можете начать регулярные обновления, вызвав requestLocationUpdates().

В зависимости от формы запроса объединенный поставщик местоположения либо вызывает метод обратного вызова LocationCallback.onLocationChanged() и передает ему список объектов Location, либо выдает PendingIntent, который содержит местоположение в своих расширенных данных. На точность и частоту обновлений влияют запрошенные вами разрешения на определение местоположения и параметры, заданные вами в объекте запроса на определение местоположения.

В этом уроке показано, как получить обновление с помощью обратного вызова LocationCallback. Вызовите requestLocationUpdates(), передав ему свой экземпляр объекта LocationRequest и LocationCallback. Определите метод startLocationUpdates(), как показано в следующем примере кода:

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

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

Подробное описание ознакомьтесь с официальной документацией.

Надеюсь это поможет.

person Mayank Bhatnagar    schedule 05.07.2018