本文介绍了Android WorkManager不会触发两个预定的工作程序之一的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用中安排了两名定期工作的工人,其中一名工人在24小时后重复一次,另一名在15分钟后重复一次.

I have two periodic workers scheduled in my app where one worker repeats after 24 hours and another in 15 minutes.

最初,在全新安装中,一切正常,但几天后,我在2台设备(5台设备)中遇到问题.正确触发了24小时工作人员,但根本没有触发15分钟的工作人员.我已经对此进行了24小时的监控.

Initially on fresh install things work as expected, but after some days I got an issue on 2 devices(out of 5).The 24 hour worker is triggered properly but the 15 minute one isn't triggered at all. I have been monitoring this for 24 hours now.

我通过Stetho查看了工作经理的数据库,看到一些24小时工作人员的条目和0个15分钟工作人员的条目.我正在查看 WorkSpec 表.

I viewed the databse of workmanager via Stetho and saw some entries for 24-hour worker and 0 entries for 15 minute worker. I'm looking in the WorkSpec table.

我通过Android Studio进行了调试,并使用 getWorkInfosByTag()查询WorkManager后,我得到了一个15分钟工作人员的80个对象的列表,其中79个处于 CANCELED 状态,一个处于 ENQUEUED 状态.

I debugged via Android studio and after querying WorkManager using getWorkInfosByTag() I got a list of 80 objects for the 15-minute worker where 79 were in CANCELED state and one was in ENQUEUED state.

那么,显然,被取消的工作人员不会添加到数据库中吗?

So apparently, canceled workers are not added to the DB?

我没有从Google找到任何文档来说明取消工作人员的情况.

I did not find any document from Google which explains the scenarios in which worker is canceled.

我正在使用工作运行时的 1.0.0-beta03 版本.另外,我并没有杀死该应用程序或做任何有趣的事情.该应用程序在后台运行,没有被杀死.设备为Mi A2(Android 9),Redmi Note 4(Android 7).

I am using 1.0.0-beta03 version of the work runtime.Also, I am not killing the app or doing anything funny. The app is running in the background and not being killed.Devices are Mi A2 (Android 9), Redmi Note 4(Android 7).

我需要了解为什么取消该工作程序,还有什么更好的方法来调试它?任何指针都将是有帮助的,并且会被批评!

I need to understand why is the worker being canceled and is there any better way to debug this? Any pointers will be helpful and upvoted!

谢谢.

Edit1:发布代码以安排两名工作人员.

Posting the code to schedule both workers.

24小时定期工作的工人:

24-hour periodic worker:

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分钟的定期工作者:

15-minute periodic worker:

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.");
    }
}

注意:设备已连接到Internet&网络速度还不错.

Note: The device is connected to the Internet & network speed is pretty good.

推荐答案

已解决:WorkManager未触发工作程序

在进行一些调试后解决了该问题.如果有人遇到相同问题,请在此处发布.

SOLVED: Worker not being triggered by WorkManager

Resolved the issue after some debugging. Posting here in case someone runs into the same issue.

所以,我一次又一次地取消和排队工人.因此,假设某个工作人员今天的排班时间为11.15 AM,然后我取消并重新排队,因为没有为新排队的工作人员分配11.15 AM的时间段.

So, I was canceling and enqueuing workers again and again. So lets say a worker is scheduled for 11.15 AM today, then I cancel and enqueue again, the 11.15 AM slot was not being given to the newly enqueued worker.

相反,当使用11.15 AM插槽时,工作经理只是检查排定的工作人员是否已取消,并且不会触发新排队的工作人员.

Instead, When the 11.15 AM slot is utilised, the work manager just checks that the scheduled worker was canceled and does not trigger the newly enqueued worker.

这是我们测试的5台设备中有3台的行为.在2台设备上,已正确触发了新入队的工作程序.

This was the behaviour on 3 out of 5 devices we tested on. On 2 devices the newly enqueued worker was properly being triggered.

现在的解决方案:

  1. 删除所有代码以安排您的工作人员.

  1. Remove all code to schedule your workers.

在应用程序的 onCreate()中,首先在 WorkManager 上调用 pruneWork(),以删除所有堆积的取消的工作程序时间表.请记住,该方法返回 Operation ,它将帮助您检查删除操作是否完成.在调用 pruneWork()之前,您还可以为所有工作人员调用 cancelAllWorkByTag(),以清理所有待处理的计划.此方法还返回 Operation .

In the onCreate() of your application, first invoke pruneWork() on WorkManager to remove all piled up cancelled worker schedules. Remember the method returns Operation which will help you check the completion of removal.Before calling pruneWork() you might also call cancelAllWorkByTag() for all your workers to clean up any and all the pending schedules. This method also returns an Operation.

在清除工作经理的日程之后,您现在可以按自己的方式安排 PeriodicWorkRequest .我使用了 enqueueUniquePeriodicWork()来确保一次仅运行一个worker实例.

After the work manager schedules are cleared, you can now schedule your PeriodicWorkRequest the way you want. I used enqueueUniquePeriodicWork() to make sure only one instance of worker is running at a time.

现在,我的工作人员每15分钟被正确触发一次.

Now, my worker is being triggered every 15 minutes properly.

请注意,当您的设备进入睡眠模式并进入休眠模式时,这15分钟的持续时间将会增加.

Note that as and when your device sleeps and goes into doze mode, this 15 minute duration will increase.

您可以使用Stetho库检查工作管理器数据库.该表的名称为 WorkSpec ,您将在其中找到所有工作人员的时间表.而且,您可以在某个断点处停止应用程序的执行,并在 WorkManager 上使用 getWorkInfosByTag()来获取日程表及其当前状态的列表.

You can check the work manager database using Stetho library.The table name is WorkSpec where you'll find all the schedules for your workers. And you can stop app execution at some breakpoint and use getWorkInfosByTag() on WorkManager to get a list of schedules and their current status.

这篇关于Android WorkManager不会触发两个预定的工作程序之一的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 10:13