Почему LocationCallback не запускается в CallbackToFutureAdapter? - PullRequest
0 голосов
/ 17 апреля 2020

Что мне нужно сделать sh: мое приложение должно запрашивать текущее местоположение пользователя, повторяя каждые 15 минут, также в фоновом режиме и даже когда приложение закрывается.

Что я сделал: я использую FusedLocationProviderAPI, вызываемый внутри периодического WorkManager, расширяющий ListenableWorker, поскольку API является асинхронным. Каждый раз, когда система предоставляет новое Обновление местоположения (максимум каждые пятнадцать минут), вызывается LocationCallback.

Поскольку ResolvableFuture кажется устаревшим для использования в startWork-методе ListenableWorker, я использую CallbackToFutureAdapter. В этом адаптере я инициализирую LocationCallback и вызываю метод doWork, который включает все логи c для запроса информации.

Моя проблема: Когда экран активен, все отлично работает . Но как только приложение запускается в фоновом режиме или завершается, LocationCallback не будет вызываться. (последний журнал: «Ожидание обратного вызова»). Обратите внимание, что я удалил большие фрагменты кода ниже (например, обработку исключений и детали).

Вот мой код в MyWorker расширяет ListenWower startWork-Method:

public ListenableFuture<Result> startWork() {
        return CallbackToFutureAdapter.getFuture(completer -> {

            mLocationCallback = new LocationCallback() {

                @Override
                public void onLocationResult(LocationResult locationResult) {
                    super.onLocationResult(locationResult);

                   // Storing data to different repositories.

                    completer.set(Result.success());
                }

            };
            doWork();

            return "startSomeAsyncStuff";
        });
    } 

doWork ():

public Result doWork() {

               mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext);
                mSettingsClient = LocationServices.getSettingsClient(mContext);
                createLocationCallback();
                createLocationRequest();
                buildLocationSettingsRequest();

               startLocationUpdates();

        return Result.success();
    }

startLocationUpdates ():

 private void startLocationUpdates() {
        // Begin by checking if the device has the necessary location settings.
        mSettingsClient.checkLocationSettings(mLocationSettingsRequest)
                .addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
                    @Override
                    public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                        Log.i(TAG, "All location settings are satisfied.");
                        mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper());
                   Log.i(TAG, "Location updated requested - Waiting for Callback");

                    }
                })

Похожие записи: Как вернуть ListenableFuture с диспетчером работ 2.0? и WorkManager: ResolvableFuture может вызываться только из одного префикса группы библиотек

1 Ответ

0 голосов
/ 27 апреля 2020

Итак, после нескольких часов проб и ошибок вот решение, которое наконец-то работает для меня:

Хитрость заключается в добавлении Foreground-Service, который гарантирует, что работник не будет отменен, до нового Location- Обновление поступает из системы. Тем не менее, вы не можете не показывать уведомления в течение этого периода времени. Я также переместил LocationCallback в метод doWork, непосредственно перед запросом обновлений местоположения (поскольку вам нужно передать обратный вызов этому методу).

Это решение основано на https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running, на который я должен был взглянуть вначале, чтобы избавить меня от разочарования;)

Вот startWork () - Метод:

 public ListenableFuture<Result> startWork() {
        return CallbackToFutureAdapter.getFuture(completer -> {
            setForegroundAsync(createForegroundInfo());

            doWork(completer);

            // This value is used only for debug purposes: it will be used
            // in toString() of returned future or error cases.
            return "Location Worker";
        });
    }
...