使用 WorkManager 在特定时间安排工作
Schedule a work on a specific time with WorkManager
WorkManager is a library used to enqueue work that is guaranteed to execute after its constraints are met.
因此,在早上通过 Constraints class I haven't found any function to add time constraint on the work. For like example, I want to start a work to perform at 8:00am (The work can be any of two types OneTimeWorkRequest or PeriodicWorkRequest) 之后。我如何添加约束以使用 WorkManager 安排这项工作。
很遗憾,您目前无法在特定时间安排工作。如果你有时间关键的实现,那么你应该使用 AlarmManager 来设置可以在打瞌睡时触发的警报,方法是使用 setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
您可以使用 WorkManager
安排工作,使用一次性初始延迟或定期执行,如下所示:
创建工人class:
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 小时定期一次。
到目前为止,使用 PeriodicWorkRequest
.
无法获得准确的时间
一个丑陋的解决方法是使用 OneTimeWorkRequest
,当它触发时,设置另一个 OneTimeWorkRequest
和新的计算周期,依此类推。
您可以使用印象笔记中的 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
}
}
}
然后在您的应用程序中启动 class
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'
}
如果您想将初始延迟设置为 PeriodicWorkRequest,我在此处介绍了解决方案:
Set initial delay to a Periodic Work Manager in Android
所有答案现已过时,请升级到 WorkManager 2.1.0-alpha02(或更高版本)
setInitialDelay() 方法过去只对 OneTimeWorkRequest 起作用,但现在它们也支持 PeriodicWorkRequest。
implementation "androidx.work:work-runtime:2.1.0-alpha02"
PeriodicWorkRequests now support initial delays. You can use the
setInitialDelay method on PeriodicWorkRequest.Builder to set an
initial delay
快速示例:
new PeriodicWorkRequest.Builder(MyWorker.class, MY_REPEATS, TimeUnit.HOURS)
.setInitialDelay(THE_DELAY,TimeUnit.SECONDS);
从版本 2.1.0-alpha02 开始,PeriodicWorkRequests 现在支持初始延迟。您可以使用 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);
我可能有点晚了,但无论如何我这样做是为了在给定时间安排 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);
}
我试过 OneTimeWorkRequest 但它不稳定(有时只工作)所以我们不应该依赖它。 AlarmManager 是一个更好的选择。
WorkManager is a library used to enqueue work that is guaranteed to execute after its constraints are met.
因此,在早上通过 Constraints class I haven't found any function to add time constraint on the work. For like example, I want to start a work to perform at 8:00am (The work can be any of two types OneTimeWorkRequest or PeriodicWorkRequest) 之后。我如何添加约束以使用 WorkManager 安排这项工作。
很遗憾,您目前无法在特定时间安排工作。如果你有时间关键的实现,那么你应该使用 AlarmManager 来设置可以在打瞌睡时触发的警报,方法是使用 setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
您可以使用 WorkManager
安排工作,使用一次性初始延迟或定期执行,如下所示:
创建工人class:
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 小时定期一次。
到目前为止,使用 PeriodicWorkRequest
.
无法获得准确的时间
一个丑陋的解决方法是使用 OneTimeWorkRequest
,当它触发时,设置另一个 OneTimeWorkRequest
和新的计算周期,依此类推。
您可以使用印象笔记中的 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
}
}
}
然后在您的应用程序中启动 class
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'
}
如果您想将初始延迟设置为 PeriodicWorkRequest,我在此处介绍了解决方案:
Set initial delay to a Periodic Work Manager in Android
所有答案现已过时,请升级到 WorkManager 2.1.0-alpha02(或更高版本) setInitialDelay() 方法过去只对 OneTimeWorkRequest 起作用,但现在它们也支持 PeriodicWorkRequest。
implementation "androidx.work:work-runtime:2.1.0-alpha02"
PeriodicWorkRequests now support initial delays. You can use the setInitialDelay method on PeriodicWorkRequest.Builder to set an initial delay
快速示例:
new PeriodicWorkRequest.Builder(MyWorker.class, MY_REPEATS, TimeUnit.HOURS)
.setInitialDelay(THE_DELAY,TimeUnit.SECONDS);
从版本 2.1.0-alpha02 开始,PeriodicWorkRequests 现在支持初始延迟。您可以使用 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);
我可能有点晚了,但无论如何我这样做是为了在给定时间安排 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);
}
我试过 OneTimeWorkRequest 但它不稳定(有时只工作)所以我们不应该依赖它。 AlarmManager 是一个更好的选择。