使用WorkManager在特定时间安排工作

Cod*_*meo 37 android android-workmanager

WorkManager是一个用于排队工作的库,保证在满足约束条件后执行.

因此,在通过Constraints类之后,我没有找到任何函数来为工作添加时间约束.例如,我想在上午8:00开始工作(工作可以是OneTimeWorkRequestPeriodicWorkRequest中的任何一种).如何使用WorkManager添加约束来安排此工作.

Sag*_*gar 32

不幸的是,截至目前,您无法在特定时间安排工作.如果您有时间关键的实现,那么您应该使用AlarmManager来设置在Doze中可以使用setAndAllowWhileIdle()setExactAndAllowWhileIdle()触发的警报.

您可以使用以下内容安排工作,一次性初始延迟或定期执行WorkManager:

创建Worker类:

public class MyWorker extends Worker {
    @Override
    public Worker.WorkerResult doWork() {

        // Do the work here

        // Indicate success or failure with your return value:
        return WorkerResult.SUCCESS;

        // (Returning RETRY tells WorkManager to try this task again
        // later; FAILURE says not to try again.)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后安排OneTimeWorkRequest如下:

OneTimeWorkRequest mywork=
        new OneTimeWorkRequest.Builder(MyWorker.class)
        .setInitialDelay(<duration>, <TimeUnit>)// Use this when you want to add initial delay or schedule initial work to `OneTimeWorkRequest` e.g. setInitialDelay(2, TimeUnit.HOURS)
        .build();
WorkManager.getInstance().enqueue(mywork);
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式设置其他约束:

// Create a Constraints that defines when the task should run
Constraints myConstraints = new Constraints.Builder()
    .setRequiresDeviceIdle(true)
    .setRequiresCharging(true)
    // Many other constraints are available, see the
    // Constraints.Builder reference
     .build();
Run Code Online (Sandbox Code Playgroud)

然后创建一个使用这些约束的OneTimeWorkRequest

OneTimeWorkRequest mywork=
                new OneTimeWorkRequest.Builder(MyWorker.class)
     .setConstraints(myConstraints)
     .build();
WorkManager.getInstance().enqueue(mywork);
Run Code Online (Sandbox Code Playgroud)

PeriodicWorkRequest可以创建如下:

 PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(MyWorker.class, 12, TimeUnit.HOURS)
                                   .build();
  WorkManager.getInstance().enqueue(periodicWork);
Run Code Online (Sandbox Code Playgroud)

这会创建一个PeriodicWorkRequest,每12个小时定期运行一次.

  • 这个答案是如何被接受的?问题是我们要在早上8点执行这项工作.没有提到那个? (15认同)
  • 问题是它不适用于定期工作. (4认同)
  • setInitialDelay有两种方法,一种是期望持续时间作为参数,仅在API 26中(因为它来自Java 8),另一种需要持续时间和时间单位,在每个平台上都可用. (3认同)
  • 这是因为您无法在特定时间使用 WorkManager 安排工作 (3认同)
  • @Gatek,它的整体.它在Google IO中被提及.如果你想这样做,那么Schedule OneTimeWorkRequest将在2小时后触发,PeriodicWorkRequest将在下午2点执行. (2认同)

小智 8

我可能有点晚了,但无论如何,我这样做是为了在给定时间安排工作请求(带有可选的短暂延迟)。您只需要从 TimePicker 中获取时间即可:

public static void scheduleWork(int hour, int minute) {
    Calendar calendar = Calendar.getInstance();
    long nowMillis = calendar.getTimeInMillis();

    calendar.set(Calendar.HOUR_OF_DAY,hour);
    calendar.set(Calendar.MINUTE,minute);
    calendar.set(Calendar.SECOND,0);
    calendar.set(Calendar.MILLISECOND,0);

    if (calendar.before(Calendar.getInstance())) {
        calendar.add(Calendar.DATE, 1);
    }

    long diff = calendar.getTimeInMillis() - nowMillis;

    WorkManager mWorkManager = WorkManager.getInstance();
    Constraints constraints = new Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build();
    mWorkManager.cancelAllWorkByTag(WORK_TAG);
    OneTimeWorkRequest mRequest = new OneTimeWorkRequest.Builder(NotificationWorker.class)
            .setConstraints(constraints)
            .setInitialDelay(diff,TimeUnit.MILLISECONDS)
            .addTag(WORK_TAG)
            .build();
    mWorkManager.enqueue(mRequest);

}
Run Code Online (Sandbox Code Playgroud)


mha*_*im6 6

到目前为止,无法使用确切的时间PeriodicWorkRequest.
一个丑陋的解决方法是使用a OneTimeWorkRequest,当它触发时,OneTimeWorkRequest用新的计算周期设置另一个,依此类推.

  • 哇......那是非常恶心的xx (15认同)
  • @Kerooker实际上,这是由 WorkManager 的开发人员之一建议的[此处](https://youtu.be/n9r5OCb7Qb8?t=1463) (3认同)

Anj*_*een 5

现在,PeriodicWorkRequests支持版本2.1.0-alpha02的初始延迟。您可以在PeriodicWorkRequest.Builder上使用setInitialDelay方法来设置初始延迟。在这里链接

每天上午8:00的时间表示例。在这里,我使用joda时间库进行时间操作。

final int SELF_REMINDER_HOUR = 8;

    if (DateTime.now().getHourOfDay() < SELF_REMINDER_HOUR) {
        delay = new Duration(DateTime.now() , DateTime.now().withTimeAtStartOfDay().plusHours(SELF_REMINDER_HOUR)).getStandardMinutes();
    } else {
        delay = new Duration(DateTime.now() , DateTime.now().withTimeAtStartOfDay().plusDays(1).plusHours(SELF_REMINDER_HOUR)).getStandardMinutes();
    }


    PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(
        WorkerReminderPeriodic.class,
        24,
        TimeUnit.HOURS,
        PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS,
        TimeUnit.MILLISECONDS)
        .setInitialDelay(delay, TimeUnit.MINUTES)
        .addTag("send_reminder_periodic")
        .build();


    WorkManager.getInstance()
        .enqueueUniquePeriodicWork("send_reminder_periodic", ExistingPeriodicWorkPolicy.REPLACE, workRequest);
Run Code Online (Sandbox Code Playgroud)