使用WorkManager

时间:2018-05-16 06:09:32

标签: android android-workmanager

  

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

因此,在完成Constraints课程之后,我还没有找到任何增加工作时间限制的功能。例如,我想在上午8:00开始工作(工作可以是两种类型中的任何一种OneTimeWorkRequestPeriodicWorkRequest)。如何使用WorkManager添加约束来安排此工作。

8 个答案:

答案 0 :(得分:25)

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

您可以使用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

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

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

// 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();

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

OneTimeWorkRequest mywork=
                new OneTimeWorkRequest.Builder(MyWorker.class)
     .setConstraints(myConstraints)
     .build();
WorkManager.getInstance().enqueue(mywork);

可以按如下方式创建PeriodicWorkRequest:

 PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(MyWorker.class, 12, TimeUnit.HOURS)
                                   .build();
  WorkManager.getInstance().enqueue(periodicWork);

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

答案 1 :(得分:5)

到目前为止,无法使用m = as.matrix(read.table(header=T, text=' A B C D "0/0" "0/1" "0/0" "1/1" "1/1" "1/1" "0/1" "0/1" "1/2" "0/3" "1/1" "2/2" "0/0" "0/0" "2/2" "0/0" "0/0" "0/0" "0/0" "0/0"')) m = do.call(cbind, replicate(40 , m, simplify = FALSE)) m = do.call(rbind, replicate(3000, m, simplify = FALSE)) colnames(m) = paste0("A", 1:160) 获得准确的时间。
一个丑陋的解决方法将使用PeriodicWorkRequest,并且在触发时,使用新的计算周期设置另一个OneTimeWorkRequest,依此类推。

答案 2 :(得分:2)

我可能会迟到一些,但是无论如何我都是这样做的,目的是在给定的时间安排WorkRequest(有一个可选的短暂延迟)。您只需要从TimePicker获取以下时间即可:

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

}

答案 3 :(得分:1)

您可以从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
           }
       }
  }

然后在您的Application类中启动

    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'
    }

答案 4 :(得分:0)

如果您要将初始延迟设置为 PeriodicWorkRequest ,我在此处介绍了解决方案:

Set initial delay to a Periodic Work Manager in Android

答案 5 :(得分:0)

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

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

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

快速示例:

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

答案 6 :(得分:0)

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

每天8:00的时间表示例。这里我使用joda time library进行时间操作。

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

答案 7 :(得分:0)

我尝试过OneTimeWorkRequest,但它很不稳定(有时只能工作),因此我们不应该依赖它。 AlarmManager是更好的选择。