Android WorkManager api для выполнения ежедневной задачи в фоновом режиме

Мне нужно вызывать один API ежедневно в фоновом режиме, даже если приложение закрыто. Я видел о API WorkManager. Для моего сценария я попробовал PeriodicWorkRequest, но, к сожалению, он не работает как ожидаемый результат. То, что я сделал, я использовал этот код в классе Application

 PeriodicWorkRequest.Builder myWorkBuilder =
                new PeriodicWorkRequest.Builder(MyWorker.class, 24,
                        TimeUnit.HOURS);

        PeriodicWorkRequest myWork = myWorkBuilder.build();
        WorkManager.getInstance().enqueue(myWork);

Но он работает несколько раз в 11 раз, когда приложение открыто в первый раз после этого, оно не работает через 24 часа. Пожалуйста, кто-нибудь, помогите мне решить.

Ответы

Ответ 1

Если вы хотите, чтобы PeriodicWorkRequest не создавался несколько раз, вы можете использовать метод WorkManager.enqueueUniquePeriodicWork для планирования вашего работника:

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


Например:

PeriodicWorkRequest.Builder myWorkBuilder =
            new PeriodicWorkRequest.Builder(MyWorker.class, 24, TimeUnit.HOURS);

PeriodicWorkRequest myWork = myWorkBuilder.build();
WorkManager.getInstance()
    .enqueueUniquePeriodicWork("jobTag", ExistingPeriodicWorkPolicy.KEEP, myWork);

Ответ 2

Я думаю, что есть три проблемы.

1) Вы создаете новую периодическую работу каждый раз, когда вы enqueue myWork в экземпляр WorkManager.

Попробуйте, логика в doWork() вашего MyWorker.class выполняется один раз в первый раз, выполняется дважды во второй раз. Вы, скорее всего, добавили 11 работ в Work Manager, и именно поэтому он выполнялся 11 раз, в последний раз, когда вы проверяли. Если вы создаете новые работы и добавляете их в рабочий диспетчер, количество myWork увеличивается.

Подобно Job Scheduler, вы должны проверить, существует ли работа или нет, прежде чем добавлять ее в Work Manager.

Образец кода:

final WorkManager workManager = WorkManager.getInstance();
final LiveData<List<WorkStatus>> statusesByTag = workManager
        .getStatusesByTag(TAG_PERIODIC_WORK_REQUEST);

    statusesByTag.observe(this, workStatuses -> {
    if (workStatuses == null || workStatuses.size() == 0) {
        Log.d(TAG, "Queuing the Periodic Work");
        // Create a periodic request
        final PeriodicWorkRequest periodicWorkRequest =
                new PeriodicWorkRequest.Builder(SyncWorker.class, 30, TimeUnit.MINUTES)
                        .addTag(TAG_PERIODIC_WORK_REQUEST)
                        .build();

        // Queue the work
        workManager.enqueue(periodicWorkRequest);
    } else {
        Log.d(TAG, "Work Status Size: " + workStatuses.size());
        for (int i = 0; i < workStatuses.size(); i++) {
            Log.d(TAG, "Work Status Id: " + workStatuses.get(i).getId());
            Log.d(TAG, "Work Status State: " + workStatuses.get(i).getState());
        }
        Log.d(TAG, "Periodic Work already exists");
    }
});

В приведенном выше примере я использую уникальный тег TAG_PERIODIC_WORK_REQUEST для идентификации моей периодической работы и проверки ее TAG_PERIODIC_WORK_REQUEST или отсутствия до ее создания.

2) Ваша работа может не работать, когда приложение будет убито.

Что такое бренд, на котором вы тестируете? Это Xiaomi? Вы тестировали его на нескольких других брендах и получили тот же результат?

Был ли он в режиме "Доза"? И как вы подтверждаете, что работа не выполняется, когда вы устанавливаете время в 24 часа?

Work Manager обеспечивает обратную совместимость, но все же вам необходимо обрабатывать логику устройства. На устройствах Xiaomi, аналогичных планировщику заданий (или диспетчеру задания Firebase или сигналу тревоги), периодическая работа прекращается, когда приложение убито.

3) Я просто думаю, что PeriodicWorkRequest предоставленный WorkManager, глючит.

Я тестировал его с начала предыдущей недели на нескольких устройствах. Я создал работу, когда приложение было запущено в первый раз и не открывало его в течение трех дней. Он запускался один раз в первый раз, два раза, когда вторая синхронизация запускалась и между ними, она увеличивалась до 13 раз, снижалась до 1 раза, 4 раза и т.д..

В другом тесте я создал работу с приведенным ниже кодом во время первой установки и удалил код из второй установки. Во время этого теста, даже если работа была успешно завершена, работа запускается каждый раз, приложение открывается после его убийства.

final PeriodicWorkRequest periodicWorkRequest =
            new PeriodicWorkRequest.Builder(SyncWorker.class, 30, TimeUnit.MINUTES)
                    .addTag("periodic-work-request")
                    .build();

// Queue the work
WorkManager.getInstance().enqueue(periodicWorkRequest);

Я понимаю это, поскольку он все еще находится в альфе. Я не думаю, что вы должны использовать его в производстве.

Ответ 3

Если вы добавите тег в PeriodicWorkRequestBuilder, а затем вызовите WorkManager.getInstance().cancelAllWorkByTag(REQUEST_TAG) прежде чем вы ставите в очередь периодический запрос, который будет препятствовать обманам:

Android Workmanager PeriodicWorkRequest не уникален

Ответ 4

Начиная с alpha03 вы можете запланировать уникальную периодическую работу: https://developer.android.com/jetpack/docs/release-notes

WorkManager.enqueueUniquePeriodicWork(String uniqueWorkName, ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy, PeriodicWorkRequest periodWork) позволяет вставить в очередь уникальный PeriodicWorkRequest

Поэтому гораздо проще добиться того, чего вы хотите сейчас.

Ответ 5

В alpha 01 была проблема, которая:

Исправлена проблема, из-за которой работники были перенесены на Application.onCreate().

Используйте последнюю версию WorkManager, то есть 1.0.0-alpha02. Ознакомьтесь с примечаниями к выпуску для получения дополнительной информации.

Ответ 6

Используйте WorkManager версии 1.0.0-alpha04. Вы можете проверить примечания к выпуску здесь

Кроме того, обратитесь к этой демоверсии PeriodicWorkRequest GitHub, которая обновляет счетчик дней один раз в день (каждые 24 часа) во время окна обслуживания. Он выполняет метод doWork(), независимо от того, открыто или закрыто приложение.

WorkManager все еще находится в альфа-режиме, поэтому он будет работать полностью для всех устройств после выпуска окончательной версии.