Android WorkManager не запускает одного из двух запланированных рабочих - PullRequest
0 голосов
/ 31 января 2019

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

Первоначально при новой установке все работало, как и ожидалось, но через несколько дней у меня возникла проблема 2устройства (из 5).24-часовой рабочий запускается правильно, а 15-минутный - вообще не срабатывает.Я наблюдаю за этим в течение 24 часов.

Я просмотрел базу данных workmanager через Stetho и увидел несколько записей для 24-часового работника и 0 записей для 15-минутного работника.Я смотрю в таблицу WorkSpec.

Я отлаживал через Android-студию и после запроса WorkManager с помощью getWorkInfosByTag() я получил список из 80 объектов для 15-минутного работника, где 79 были в CANCELEDсостояние и один находился в состоянии ENQUEUED.

Итак, очевидно, уволенные работники не добавляются в БД?

Я не нашел ни одного документа от Google, в котором объясняются сценарии, в которых работникотменено.

Я использую 1.0.0-beta03 версию рабочей среды выполнения.Кроме того, я не убиваю приложение и не делаю ничего смешного.Приложение работает в фоновом режиме и не убивается.Устройства Mi A2 (Android 9), Redmi Note 4 (Android 7).

Мне нужно понять, почему увольняют работника и есть ли лучший способ отладить это?Любые указатели будут полезны и проголосовали!

Спасибо.

Edit1: публикация кода для планирования обоих работников.

24-часовой периодический работник:

public static synchronized void scheduleWork() {
    checkPreviousWorkerStatus();
    if (isWorking()) {
        Log.i("AppDataCleanupWorker", "Did not schedule data cleanup work; already running.");
        return;
    }

    if (lastWorkId != null) {
        WorkManager.getInstance().cancelAllWorkByTag("AppDataCleanupWorker");
        lastWorkId = null;
    }

    Constraints constraints = new Constraints.Builder()
            .setRequiresCharging(true)
            .build();

    PeriodicWorkRequest.Builder builder = new PeriodicWorkRequest
            .Builder(AppDataCleanupWorker.class, 24, TimeUnit.HOURS)
            .addTag("AppDataCleanupWorker")
            .setConstraints(constraints);

    PeriodicWorkRequest workRequest = builder.build();
    lastWorkId = workRequest.getId();
    WorkManager.getInstance().enqueue(workRequest);

    List<WorkInfo> workInfos = WorkManager.getInstance()
            .getWorkInfosByTagLiveData("AppDataCleanupWorker")
            .getValue();
    if (workInfos != null && workInfos.size() > 1) {
        throw new RuntimeException("Multiple workers scheduled. Only one schedule is expected.");
    }
}

15-минутный периодический работник:

public static synchronized void scheduleWork() {
    checkPreviousWorkerStatus();
    if (isWorking) {
        Log.i("ImageUploadWorker", "Did not schedule image upload work; already running.");
        return;
    }

    if (lastWorkId != null) {
        WorkManager.getInstance().cancelAllWorkByTag("ImageUploadWorker");
        lastWorkId = null;
    }

    Constraints constraints = new Constraints.Builder()
            .setRequiresBatteryNotLow(true)
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build();
    PeriodicWorkRequest.Builder builder =
            new PeriodicWorkRequest.Builder(ImageUploadWorker.class, 15,
                    TimeUnit.MINUTES)
                    .addTag("ImageUploadWorker")
                    .setConstraints(constraints);
    PeriodicWorkRequest workRequest = builder.build();
    lastWorkId = workRequest.getId();
    WorkManager.getInstance().enqueue(workRequest);

    List<WorkInfo> workInfos = WorkManager.getInstance()
            .getWorkInfosByTagLiveData("ImageUploadWorker").getValue();
    if (workInfos != null && workInfos.size() > 1) {
        throw new RuntimeException("Multiple workers scheduled. Only one schedule is expected.");
    }
}

Примечание. Устройство подключено к Интернету, скорость сети довольно хорошая.

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Вы делаете несколько неправильных вещей.

  1. Вы используете LiveData и вызываете для него функцию getValue () без добавления Observer.Это не даст вам того, что вы ищете - LiveData никогда не начнет отслеживать нужные вам значения.Пожалуйста, проверьте правильное использование LiveData здесь: https://developer.android.com/topic/libraries/architecture/livedata

  2. Если вам нужна только одна конкретная копия типа работы, вы должны использовать enqueueUniqueWork вместо enqueue.

  3. Если вы не оказались в крайне плохой ситуации, когда вам действительно нужно удалить старых работников, я бы посоветовал вам не вызывать pruneWork ().Пожалуйста, смотрите документацию: https://developer.android.com/reference/androidx/work/WorkManager#pruneWork()

0 голосов
/ 31 января 2019

решено: WorkManager не вызвал работника

Устранена проблема после некоторой отладки.Публикация здесь на случай, если кто-то столкнется с той же проблемой.

Итак, я снова и снова отменял и ставил рабочих в очередь.Допустим, рабочий назначен на 11.15 на сегодня, затем я отменяю и снова ставлю в очередь, слот 11.15 не был передан вновь ставленному рабочему.

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

Это было поведение на 3 из 5 протестированных нами устройств.На 2 устройствах только что поставленный в очередь работник был правильно запущен.

Теперь решение:

  1. Удалите весь код для планирования ваших работников.

  2. В onCreate() вашего приложения сначала вызовите pruneWork() на WorkManager, чтобы удалить все накопленные отмененные рабочие графики.Помните, что метод возвращает Operation, который поможет вам проверить завершение удаления.Перед тем, как позвонить pruneWork(), вы также можете позвонить cancelAllWorkByTag(), чтобы все ваши работники убрали все отложенные графики.Этот метод также возвращает Operation.

  3. После того, как расписания диспетчера работ очищены, вы можете теперь планировать PeriodicWorkRequest так, как вы хотите.Я использовал enqueueUniquePeriodicWork(), чтобы убедиться, что одновременно запущен только один экземпляр работника.

Теперь мой работник запускается каждые 15 минут должным образом.

Обратите внимание, что по мере того, как и когда ваше устройство спит и переходит в режим ожидания, эта 15-минутная продолжительность увеличивается.

Вы можете проверить базу данных диспетчера работ с помощью библиотеки Stetho.Имя таблицы - WorkSpec, где вы найдете все графики для ваших работников.И вы можете остановить выполнение приложения на некоторой точке останова и использовать getWorkInfosByTag() на WorkManager, чтобы получить список расписаний и их текущий статус.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...