用于在后台运行日常任务的Android WorkManager api

用于在后台运行日常任务的Android WorkManager api,android,android-jobscheduler,android-jetpack,android-workmanager,Android,Android Jobscheduler,Android Jetpack,Android Workmanager,我需要每天在后台调用一个API,即使应用程序已关闭。我已经了解了WorkManager API。在我的场景中,我尝试了PeriodicWorkRequest,但不幸的是,它没有达到我预期的效果。我所做的是在应用程序类中使用此代码 PeriodicWorkRequest.Builder myWorkBuilder = new PeriodicWorkRequest.Builder(MyWorker.class, 24,

我需要每天在后台调用一个API,即使应用程序已关闭。我已经了解了WorkManager API。在我的场景中,我尝试了PeriodicWorkRequest,但不幸的是,它没有达到我预期的效果。我所做的是在应用程序类中使用此代码

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

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

但当应用程序第一次打开时,它会重复运行11次,24小时后就不会运行了。请大家帮我解决。

我想有三个问题

1) 每次
myWork
排入
WorkManager
实例时,您都在创建一个新的定期工作

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

与Job Scheduler类似,在将工作添加到工作管理器之前,必须检查该工作是否存在

示例代码:

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

我理解,因为它仍然在阿尔法。我认为您不应该在生产中使用它。

如果您向
PeriodicWorkRequestBuilder
添加一个标记,然后调用
WorkManager.getInstance().cancelAllWorkByTag(REQUEST\u tag)
,然后再将定期请求排队,这将防止重复发生:


alpha 01中存在以下问题:

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


使用最新版本的WorkManager,即1.0.0-alpha02。检查更多信息

alpha03
开始,您可以安排一个独特的定期工作:

WorkManager.enqueueUniquePeriodicWork(字符串uniqueWorkName, ExistingPeriodicWorkPolicy ExistingPeriodicWorkPolicy, PeriodicWorkRequest periodicWork)允许您将唯一的 周期性工作请求


因此,现在实现您想要的目标非常简单。

如果您想确保您的
周期性工作请求
不会被多次创建,您可以使用该方法安排您的工作人员:

此方法允许您将唯一命名的PeriodicWorkRequest排队,其中一次只能有一个特定名称的PeriodicWorkRequest处于活动状态。例如,您可能只希望一个同步操作处于活动状态。如果有一个挂起,您可以选择让它运行或用新工作替换它


例如:

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

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

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

此外,请参阅本手册,其中在维护窗口期间每天(每24小时)更新一次日计数器。无论应用程序是打开还是关闭,它都执行doWork()方法


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

谢谢Srikar。我正在使用小米设备,为了进行测试,我将其设置为20分钟。它运行不正常。希望我再次返回作业计划程序。在小米上,后台作业仅在将“电池节省器”选项设置为“无”时运行。不要认为
JobScheduler
也会运行。如果有,一定要让我知道。@SrikarReddy小米设备有什么问题吗?@AbhishekBatra除了“自动启动”或“电池节电禁用”之外,你有没有其他解决方案。我使用的是1.0.0-alpha02,但仍然有同样的问题。这里也一样。每次启动应用程序都会创建越来越多的作业。看起来问题仍未解决onetimerequest也有类似的选项吗?有时,同一项工作并行调用两次。如何停止此操作?@Aram您尝试过吗?是的,我尝试过,但我们需要使用Workcontinuation对象。我不知道那个选项是否更贵。有什么想法吗?根据应用程序中的最佳实践,我们应该在哪里配置作业?上面的代码片段用于在具有Android Pie(9)的设备(OnePlus 4T)中启动
PeriodicWorkRequest
,该设备不工作,WorkManager没有让工作人员排队。由于我也在这里请求有关stackoverflow的帮助:
PeriodicWorkRequest.Builder myWorkBuilder =
            new PeriodicWorkRequest.Builder(MyWorker.class, 24, TimeUnit.HOURS);

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