[Android]Android中的JobScheduler与JobService

JobScheduler是Android5.1以后加入的,这里介绍的是Android9.0的源码

Posted by 郭伟 on 2019-06-02

Summary

JobScheduler可以安排一个周期性的任务,同时与AlarmManager相比, 它可以提前设定任务的执行条件。

Source path:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
frameworks/base/core/java/android/app/job/
//处理Job的状态
JobServiceEngine.java #
//这个回调来自如JobScheduler,并在主线程运行的,耗时操作仍需要起一个子线程,否则会阻赛onStopJob
JobService.java
// 用来启动或取消 JobService
JobScheduler.java
//可以为工作排队的工作单位
JobWorkItem.java
// 这个是由系统创建并传入的,程序不应该自己创建
JobParameters.java
// 创建Job的可选参数
JobInfo.java

---
IJobCallback.aidl
IJobScheduler.aidl
IJobService.aidl
JobInfo.aidl
JobParameters.aidl
JobWorkItem.aidl

Use

JobService中有两个抽象方法onStartJob(JobParameters jobParameters),onStopJob(JobParameters jobParameters),这两个是JobServiceEngine中被系统通过aidl回调的;

[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class MyJobService extends JobService {
@Override
public boolean onStartJob(JobParameters jobParameters) {
Toast.makeText(getApplicationContext(),"onStartJob",Toast.LENGTH_SHORT).show();
//return true}如果您的服务将继续运行,则在适当时使用单独的线程
//return false}表示此作业已完成其工作
startJob();
return false;
}

private void startJob(){
JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
JobInfo jobInfo = new JobInfo.Builder
//jobId 是创建Job和取消job的标示 必须是全局唯一的,否则这个job就会被更新
(1/*int jobId*/, new ComponentName(this,MyJobService.class)/*ComponentName jobService*/)
//该Uri将利用ContentObserver来监控一个Content Uri,当且仅当其发生变化时将触发任务的执行
// .addTriggerContentUri(/*JobInfo.TriggerContentUri uri*/)
//重试策略,第一个参数时第一次尝试重试的等待间隔,单位为毫秒,第二个参数是对应的退避策略
// .setBackoffCriteria(2000/*long initialBackoffMillis*/, JobInfo.BACKOFF_POLICY_EXPONENTIAL/*int backoffPolicy*/)
//允许为与剪辑相关联的数据授予URI权限
// .setClipData(ClipData clip, int grantFlags)
//必须充电才能运行, 这里的充电只的是直接链接到充电器.
.setRequiresCharging(true/*boolean requiresCharging*/)
//设置将执行的网络流量的估计大小
// .setEstimatedNetworkBytes(long downloadBytes, long uploadBytes)
//设置网络状态
// .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
//设置任务的周期
// .setPeriodic(1000 * 10 * 15)
//设置任务常驻,即开机启动,要求RECEIVE_BOOT_COMPLETED权限
// .setPersisted(true)
// .setRequiresDeviceIdle(false)
.build();
scheduler.schedule(jobInfo);
}

@Override
public boolean onStopJob(JobParameters jobParameters) {
return false;
}
}

Common interface

addTriggerContentUri(JobInfo.TriggerContentUri uri):
添加一个TriggerContentUri,该Uri将利用ContentObserver来监控一个Content Uri,当且仅当其发生变化时将触发任务的执行。为了持续监控content的变化,你需要在最近的任务触发后再调度一个新的任务(需要注意的是触发器URI不能与setPeriodic(long)或setPersisted(boolean)组合使用。要持续监控内容更改,需要在完成JobService处理最近的更改之前,调度新的JobInfo,观察相同的URI。因为设置此属性与定期或持久化Job不兼容,这样做会在调用build()时抛出IllegalArgumentException异常。)
setBackoffCriteria(long initialBackoffMillis, int backoffPolicy):
特殊:设置回退/重试的策略,详细的可以参阅Google API。
类似网络原理中的冲突退避,当一个任务的调度失败时需要重试,所采取的策略。
第一个参数时第一次尝试重试的等待间隔,单位为毫秒,预设的参数有:
DEFAULT_INITIAL_BACKOFF_MILLIS 30000MAX_BACKOFF_DELAY_MILLIS 18000000
第二个参数是对应的退避策略,预设的参数有:
BACKOFF_POLICY_EXPONENTIAL 二进制退避。
等待间隔呈指数增长 BACKOFF_POLICY_LINEAR
setExtras(PersistableBundle extras):设置可选附件。这是持久的,所以只允许原始类型。
setMinimumLatency(long minLatencyMillis): 这个函数能用以设置任务的延迟执行时间(毫秒),相当于post delay。
setOverrideDeadline(long maxExecutionDelayMillis): 这个方法让用以设置任务最晚的延迟时间。如果到了规定的时间时其他条件还未满足,任务也会被启动。
setPeriodic(long time):设置任务运行的周期(每X毫秒,运行一次)。衍生在运行一些权限检查的时候如果可以使用job scheduler的话,可以这样来循环检查权限的开启,但是目前的触发条件没有权限部分的触发。
setPeriodic(long intervalMillis, long flexMillis):设置在Job周期末的一个flex长度的窗口,任务都有可能被执行 require API LEVEL 24
setPersisted(boolean isPersisted): 这个方法告诉系统当设备重启之后任务是否还要继续执行。
setRequiredNetworkType(int networkType): 这个方法让这个任务只有在满足指定的网络条件时才会被执行。默认条件是JobInfo.NETWORK_TYPE_NONE,这意味着不管是否有网络这个任务都会被执行。另外两个可选类型,一种是JobInfo.NETWORK_TYPE_ANY,它表明需要任意一种网络才使得任务可以执行。另一种是JobInfo.NETWORK_TYPE_UNMETERED,它表示设备不是蜂窝网络( 比如在WIFI连接时 )时任务才会被执行。
setRequiresCharging(boolean requiresCharging):只有当设备在充电时这个任务才会被执行。这个也并非只是插入充电器,而且还要在电池处于健康状态的情况下才会触发,一般来说是手机电量>15%
setRequiresDeviceIdle(boolean requiresDeviceIdle):指定Job在空闲状态才能运行。设备处于屏幕关闭或dreaming状态(类似window的休眠动画状态)71分钟后,执行工作
setTransientExtras(Bundle extras):设置可选的临时附加功能。(Android O Developer Preview)这里指定了需要Android O 系统,可以看出,Google还是在继续完善job scheduler的,期待能够代替传统的service组件成为主流。
setTriggerContentMaxDelay(long durationMs):设置从第一次检测到内容更改到Job之前允许的最大总延迟(以毫秒为单位)。说人话就是设置从content变化到任务被执行,中间的最大延迟。 同样的require API 24
setTriggerContentUpdateDelay(long durationMs):设置从content变化到任务被执行中间的延迟。如果在延迟期间content发生了变化,延迟会重新计算
setExtras(PersistableBundle extra):Bundle

$$
y = Wx + b\
\frac{\partial y}{\partial x} = W^T\
\frac{\partial y}{\partial W} = x^T
$$

Principle