Android WorkManager 不会触发两个预定的工作人员之一

Pra*_*war 7 android android-workmanager

我的应用程序中安排了两个定期工作人员,其中一个工作人员在 24 小时后重复,另一个在 15 分钟后重复。

最初在全新安装时,事情按预期工作,但几天后我在 2 台设备上遇到了问题(共 5 台)。24 小时工人被正确触发,但 15 分钟工人根本没有被触发。我现在已经监视了 24 小时。

我通过 Stetho 查看了 workmanager 的数据库,看到了一些 24 小时工人的条目和 15 分钟工人的 0 个条目。我在WorkSpec桌子上找。

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

很明显,取消的工人没有添加到数据库中?

我没有找到任何来自谷歌的文件来解释工人被取消的情况。

我正在使用1.0.0-beta03工作运行时的版本。此外,我没有杀死应用程序或做任何有趣的事情。该应用程序在后台运行,并没有被杀死。设备为小米 A2 (Android 9)、红米 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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:设备已连接到 Internet,网络速度非常好。

Pra*_*war 10

已解决:WorkManager 未触发 Worker

经过一些调试解决了这个问题。在这里发布以防有人遇到同样的问题。

所以,我一次又一次地取消和排队工人。因此,假设一个工作人员今天安排在上午 11.15 点,然后我取消并再次排队,上午 11.15 点的时间没有分配给新入队的工作人员。

相反,当使用 11.15 AM 时隙时,工作管理器只会检查已调度的工作人员是否已取消,而不会触发新入队的工作人员。

这是我们测试过的 5 个设备中的 3 个的行为。在 2 台设备上,新入队的工作人员被正确触发。

现在解决方案:

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

  2. onCreate()您的应用程序中,首先调用pruneWork()onWorkManager以删除所有堆积的已取消的工作人员计划。记住方法返回Operation,这将帮助您检查删除的完成情况。在致电之前,pruneWork()您可能还要求您cancelAllWorkByTag()的所有工作人员清理所有待处理的时间表。此方法还返回一个Operation.

  3. 清除工作经理计划后,您现在可以按照自己PeriodicWorkRequest的方式进行计划。我曾经enqueueUniquePeriodicWork()确保一次只运行一个 worker 实例。

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

请注意,当您的设备进入睡眠状态并进入打盹模式时,这 15 分钟的持续时间会增加。

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