【问题标题】:Android WorkManager api for running daily task in Background用于在后台运行日常任务的 Android WorkManager api
【发布时间】:2018-10-29 03:46:03
【问题描述】:

即使应用程序关闭,我也需要每天在后台调用一个 API。我看过 WorkManager API。对于我的场景,我尝试了 PeriodicWorkRequest 但不幸的是,它没有达到我的预期结果。我所做的是我在 Application 类中使用了这段代码

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

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

但应用程序第一次打开时重复运行11次,24小时后不再运行。请各位大神帮我解决一下。

【问题讨论】:

    标签: android android-jobscheduler android-jetpack android-workmanager


    【解决方案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);
    

    【讨论】:

    • onetimerequest 是否也有类似的选项?有时,相同的工作会被并行调用两次。如何阻止这种情况?
    • @Aram 你试过beginUniqueWork(...)吗?
    • 是的,我试过了,但我们需要使用 Workcontinuation 对象。我不知道那个选项是否更昂贵。有什么想法吗?
    • 根据最佳实践我们应该在应用程序的哪个位置配置作业?
    • 上面的代码 sn-p 在具有 Android Pie (9) 的设备 (OnePlus 4T) 中启动 PeriodicWorkRequest,不工作,WorkManager 没有将 Worker 排队。因为我也在这里寻求有关 stackoverflow 的帮助:stackoverflow.com/questions/56697105/…
    【解决方案2】:

    我认为存在三个问题。

    1) 每次 enqueue myWorkWorkManager 实例时,您都会创建一个新的周期性工作。

    试试看,MyWorker.classdoWork() 方法中的逻辑第一次运行一次,第二次运行两次。您很可能向工作管理器添加了 11 个作品,这就是您上次检查时它运行 11 次的原因。如果您创建新作品并将其添加到工作管理器中,则myWork 运行的次数会增加。

    与 Job Scheduler 类似,您必须先检查 Work 是否存在,然后才能将其添加到 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 来识别我的周期性工作,并在创建它之前检查它是否存在。

    2) 当应用被终止时,您的工作可能没有运行。

    您要测试的品牌是什么?是小米吗?您是否在其他多个品牌上进行过测试并得到相同的结果?

    是否处于打盹模式?当您设置 24 小时时间时,您如何验证工作没有运行?

    工作管理器提供向后兼容性,但您仍然需要处理设备特定的逻辑。在小米设备上,类似于 Job Scheduler(或 Firebase Job Dispatcher 或 Alarm),当应用被杀死时,周期性工作停止。

    3) 我只是觉得WorkManager 提供的PeriodicWorkRequest 有问题。

    自上周开始以来,我一直在多台设备上对其进行测试。我在第一次启动应用程序时创建了一个作品,并且三天没有打开它。第一次运行一次,触发第二次同步时运行两次,在这之间,它增加到 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);
    

    我明白,因为它仍处于 alpha 阶段。我认为您不应该在生产中使用它。

    【讨论】:

    • 谢谢 Srikar。我使用的是小米设备,为了测试,我设置了 20 分钟。它运行不正确。希望我能再次回到作业调度程序。
    • 在小米上,后台作业仅在将 省电模式 选项设置为 时运行。
    • 不要认为JobScheduler 也会运行。如果有,请告诉我。
    • @SrikarReddy 小米设备有什么破解方法吗?
    • @AbhishekBatra 除了“自动启动”或“省电模式禁用”之外,你有没有针对红米手机的任何解决方案..
    【解决方案3】:

    如果您在PeriodicWorkRequestBuilder 中添加标签,然后在将定期请求排入队列之前调用WorkManager.getInstance().cancelAllWorkByTag(REQUEST_TAG),这将防止欺骗发生:

    Android Workmanager PeriodicWorkRequest is not unique

    【讨论】:

      【解决方案4】:

      alpha03开始,您可以安排一个独特的周期性工作: https://developer.android.com/jetpack/docs/release-notes

      WorkManager.enqueueUniquePeriodicWork(String uniqueWorkName, 现有的定期工作政策现有的定期工作政策, PeriodicWorkRequest periodWork) 允许您将唯一的 定期工作请求

      所以现在实现你想要的就相当简单了。

      【讨论】:

        【解决方案5】:

        alpha 01 中存在以下问题:

        修复了导致工人在 Application.onCreate() 上重新安排的问题。

        使用最新版本的 WorkManager,即 1.0.0-alpha02。查看release notes了解更多信息

        【讨论】:

        • 我正在使用 1.0.0-alpha02 但仍然有同样的问题。
        • 这里也一样。越来越多的工作创建每个应用程序启动。
        • 看起来问题还没有解决
        【解决方案6】:

        使用 WorkManager 版本 1.0.0-alpha04。您可以查看发行说明here

        此外,请参阅此PeriodicWorkRequest GitHub demo,它在维护时段内每天(每 24 小时)更新一次日计数器。它执行 doWork() 方法,无论应用程序是打开还是关闭。

        WorkManager 仍处于 alpha 模式,因此一旦发布最终版本,它将完全适用于所有设备。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多