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

Android 使用WorkManager在特定时间安排工作,android,android-workmanager,Android,Android Workmanager,WorkManager是一个库,用于将保证在满足约束后执行的工作排队 因此,在浏览了这个类之后,我还没有找到任何函数来为工作添加时间限制。例如,我想在早上8:00开始一项工作(该工作可以是两种类型中的任何一种或两种类型)。如何使用WorkManager添加约束以安排此工作。很遗憾,您目前无法在特定时间安排工作。如果您有时间关键型实现,那么您应该使用AlarmManager通过使用或将在打瞌睡时可能触发的警报设置为 您可以使用WorkManager按如下方式安排一项具有一次性初始延迟的工作或定期执

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


因此,在浏览了这个类之后,我还没有找到任何函数来为工作添加时间限制。例如,我想在早上8:00开始一项工作(该工作可以是两种类型中的任何一种或两种类型)。如何使用WorkManager添加约束以安排此工作。

很遗憾,您目前无法在特定时间安排工作。如果您有时间关键型实现,那么您应该使用AlarmManager通过使用或将在打瞌睡时可能触发的警报设置为

您可以使用
WorkManager
按如下方式安排一项具有一次性初始延迟的工作或定期执行该工作:

创建工人类:

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.)
    }
}
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);
然后安排
OneTimeWorkRequest
如下:

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.)
    }
}
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);
然后创建使用这些约束的OneTimeWorkRequest

OneTimeWorkRequest mywork=
                new OneTimeWorkRequest.Builder(MyWorker.class)
     .setConstraints(myConstraints)
     .build();
WorkManager.getInstance().enqueue(mywork);
PeriodicWorkRequest可以按如下方式创建:
这会创建一个PeriodicWorkRequest,每12小时定期运行一次。

到目前为止,使用
PeriodicWorkRequest
无法获得准确的时间

难看的解决方法是使用
OneTimeWorkRequest
,当它触发时,用新的计算周期设置另一个
OneTimeWorkRequest
,以此类推。

您可以使用evernote的AndroidJob

class NotificationJob : DailyJob() {

override fun onRunDailyJob(params: Params): DailyJobResult {
       //your job       
       return DailyJobResult.SUCCESS

}

companion object {
    val TAG = "NotificationJob"
    fun scheduleJob() {
        //scheduled between 9-10 am

        DailyJob.schedule(JobRequest.Builder(TAG), 
            TimeUnit.HOURS.toMillis(9),TimeUnit.HOURS.toMillis(10 ))
     }
   }
 }
和通知创建者

  class NotificationJobCreator : JobCreator {

        override fun create(tag: String): Job? {
           return when (tag) {
              NotificationJob.TAG ->
                NotificationJob()
              else ->
                null
           }
       }
  }
然后在应用程序类中启动

    JobManager.create(this).addJobCreator(NotificationJobCreator())
gradle依赖是

    dependencies {
        implementation 'com.evernote:android-job:1.2.6'

        // or this with workmnager 
        implementation 'com.evernote:android-job:1.3.0-alpha08'
    }

如果要将初始延迟设置为周期性工作请求,我在这里介绍了解决方案:


现在所有答案都已过时,请升级到WorkManager 2.1.0-alpha02(或更高版本) setInitialDelay()方法仅用于OneTimeWorkRequest,但现在它们还支持PeriodicWorkRequest

implementation "androidx.work:work-runtime:2.1.0-alpha02"

PeriodicWorkRequests现在支持初始延迟。你可以使用 在PeriodicWorkRequest.Builder上设置InitialDelay方法以设置 初始延迟

快速示例:

new PeriodicWorkRequest.Builder(MyWorker.class, MY_REPEATS, TimeUnit.HOURS)
        .setInitialDelay(THE_DELAY,TimeUnit.SECONDS);

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

每天上午8:00的时间表示例。这里我用的是时间运算

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);
final int SELF\u rements\u HOUR=8;
if(DateTime.now().getHourOfDay()
我可能会有点晚,但无论如何,我这样做是为了在给定时间安排工作请求(可选的短延迟)。您只需从计时员那里获取时间:

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

    if(calendar.get(Calendar.HOUR_OF_DAY) > hour ||
            (calendar.get(Calendar.HOUR_OF_DAY) == hour && calendar.get(Calendar.MINUTE)+1 >= minute)) {
        calendar.add(Calendar.DAY_OF_MONTH, 1);
    }

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

    calendar.set(Calendar.SECOND,0);
    calendar.set(Calendar.MILLISECOND,0);
    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);

}


我试过一次工作请求,但它是脆弱的(只在有时工作),所以我们不应该依赖它。AlarmManager是一个更好的选择

?我认为,这是解决问题的好办法。为此,我必须计算当前时间和我希望开始工作的时间之间的时间差。但是,我可以明确地设置开始时间吗?计算
timeInFutureInSeconds-timenowunseconds
有什么问题吗?@pskink但是,正如问题所问,我们如何指定工作必须每天早上8点完成。?初始延迟规定为“初始”延迟。workmanager如何知道下一次我们需要运行它。由于该任务是周期性任务,workmanager将在第一次触发该任务的同时触发该任务。问题是,它在周期性工作中不起作用。@Gatek,它的整体。谷歌IO中提到了它。如果您想这样做,那么安排OneTimeWorkRequest,它将在2小时后触发,PeriodicWorkRequest将在下午2点执行。有两种方法setInitialDelay,一种方法期望将持续时间作为参数,仅在API 26中(因为它来自Java 8),另一种方法需要持续时间和时间单位,在每个平台上都可用。如何接受此答案?问题是我们必须在上午8点开始工作。没有提到这一点?这是因为你不能在特定的时间安排与WorkManager的工作哇。。。这是相当令人厌恶的。X.XI不相信有一个理由从Evernote Android工作转移到这里。请在这里回答我的问题:@ KoooKek,事实上,它是由WorkMeals@ MHHAMM6的开发人员建议的,有一些例子吗?我相信在将来,执行时间的偏移将非常大…但是用
REPLACE
对我来说似乎没问题,它只会在24小时周期结束时第一次解雇定期工。有什么方法可以让它在创建后立即工作吗?(例如,应在17:50运行,在17:40排队,并在10分钟后第一次运行)此外,如果用户更改其时间设置,工作人员将保持不变(例如,工作人员应在每天上午8:00运行。如果用户设置另一个时区,例如+3小时以上,它将不会在上午11:00运行)我尝试过,但经常无法按预期运行,因此,最好使用AlarmManager确定,如果时间是准确的,那么现在就有一天Alarm Manager没有被解雇,出于后台目的,这个答案是完美的,