作业调度:JobSchedule
Android中有很多定时任务,比如定时后台更新数据,使用AlarmManager设置(详见AlarmManager定时任务)。但是这些往往会很耗电,如果偷偷的直接执行任务,用户的电量不知不觉的没了体验很不好。推荐用Jetpack中的Jetpack定时任务利器:WorkManager!
1、JobSchedule
从API Level 21加入的JobSchedule任务调度可以设定一些执行条件,比如充电、WiFi网络等条件下才执行相应的任务。解决上面那些耗电问题。
学习标准的JobSchedule使用,可以参照Google Demo :googlearchive/android-JobScheduler
1.1、介绍
JobSchedule是系统服务,在SystemServer系统服务启动的过程中在startOtherServices()中创建初始化系统服务(见AMS服务的启动)。
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices() {
final Context context = mSystemContext;
...
traceBeginAndSlog("StartJobScheduler");
mSystemServiceManager.startService(JobSchedulerService.class);
traceEnd();
...
}1.2、获取实例
虽然JobSchedule的构造函数并不是private,理论上可以用构造函数创建JobSchedule实例(实现一堆抽象方法)。但是最好使用Context从系统服务集合中获取实例,而不是直接通过构造函数实例化。
JobScheduler jobSchedule = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);1.3、方法
①cancel(int jobId):取消指定jobID的任务
②cancelAll():取消所有本应用的调度任务
③int enqueue(JobInfo job, JobWorkItem work):和schedule(JobInfo job)相似
④List<JobInfo> getAllPendingJobs():获取应用安排的所有任务
⑤JobInfo getPendingJob(int jobId):查找指定jobID的任务
⑥int schedule(JobInfo job):计划任务(如果已成功安排此作业,则从返回RESULT_SUCCESS)。替换相同ID的作业,如果作业正在执行则会停止
此外还定义了两个任务执行结果的常量RESULT_SUCCESS和RESULT_FAILURE,分别代表任务执行成功和失败。
/** @hide */
@IntDef(prefix = { "RESULT_" }, value = {
RESULT_FAILURE,
RESULT_SUCCESS,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Result {}
/**
* Returned from {@link #schedule(JobInfo)} when an invalid parameter was supplied. This can occur
* if the run-time for your job is too short, or perhaps the system can't resolve the
* requisite {@link JobService} in your package.
*/
public static final int RESULT_FAILURE = 0;
/**
* Returned from {@link #schedule(JobInfo)} if this job has been successfully scheduled.
*/
public static final int RESULT_SUCCESS = 1;2、JobInfo
作为schedule(JobInfo job)方法的参数,JobInfo封装了任务所需的所有信息。
2.1、JobInfo.Builder
使用JobInfo.Builder构造JobInfo实例,先通过构造方法构造JobInfo.Builder实例,传入Job ID和需要执行JobInfo的JobService服务组件。
/**
* 初始化一个新的Builder来构造一个JobInfo
*
* @param jobId Application-provided id for this job. Subsequent calls to cancel, or
* jobs created with the same jobId, will update the pre-existing job with
* the same id. This ID must be unique across all clients of the same uid
* (not just the same package). You will want to make sure this is a stable
* id across app updates, so probably not based on a resource ID.
*
* @param jobService The endpoint that you implement that will receive the callback from the
* JobScheduler.
*/
public Builder(int jobId, @NonNull ComponentName jobService) {
mJobService = jobService;
mJobId = jobId;
}2.2、添加条件
①Builder setRequiredNetworkType(int networkType):任务执行所需网络条件,有下面5种:
/** Default. */
public static final int NETWORK_TYPE_NONE = 0;
/** This job requires network connectivity. */
public static final int NETWORK_TYPE_ANY = 1;
/** This job requires network connectivity that is unmetered. */
public static final int NETWORK_TYPE_UNMETERED = 2;
/** This job requires network connectivity that is not roaming. */
public static final int NETWORK_TYPE_NOT_ROAMING = 3;
/** This job requires network connectivity that is a cellular network. */
public static final int NETWORK_TYPE_CELLULAR = 4;②Builder setRequiredNetwork(NetworkRequest networkRequest)
③Builder setEstimatedNetworkBytes(long networkBytes):预估该Job下载所用流量
④Builder setEstimatedNetworkBytes(long downloadBytes,long uploadBytes):预估预估该Job下载、上传所用流量
⑤Builder setRequiresCharging(boolean requiresCharging):任务执行需要在充电条件下
⑥Builder setRequiresBatteryNotLow(boolean batteryNotLow):需要电池电量不低,具体什么标准,电量百分之几就不得而知
⑦Builder setRequiresDeviceIdle(boolean requiresDeviceIdle):设备处理IDLE状态才能执行
⑧Builder setRequiresStorageNotLow(boolean storageNotLow):需要存储空间不低
2.3、调度相关
①Builder setTriggerContentMaxDelay(long durationMs)
②Builder setTriggerContentUpdateDelay(long durationMs)
③Builder setPrefetch(boolean prefetch):将此设置为true表示此工作旨在预取内容,从而对设备的特定用户的体验产生实质性的改善。 例如,获取当前用户感兴趣的头条新闻。
④Builder setPersisted(boolean isPersisted):设置是否在重新启动设备后继续执行此作业。
⑤Builder setPeriodic(long intervalMillis):每隔intervalMillis毫秒循环执行
⑥Builder setPeriodic(long intervalMillis, long flexMillis)
⑦Builder setOverrideDeadline(long maxExecutionDelayMillis):maxExecutionDelayMillis时间后条件还没有触发立即执行
⑧Builder setMinimumLatency(long minLatencyMillis):设置任务延迟执行,不能与setPeriodic()一起使用
⑨Builder setImportantWhileForeground(boolean importantWhileForeground)
⑩Builder setPriority(int priority):应用层无法调用
⑪Builder setFlags(int flags):应用层无法调用
2.4、携带数据
使用Builder setExtras(PersistableBundle extras)方法即可,PersistableBundle继承自BaseBundle,内部有ArrayMap<String, Object>类型的mMap成员变量,携带数据,只允许基本类型的成员变量。可以在JobService方法中的JobParameters参数取出相应的数据。
示例:
PersistableBundle persistableBundle = new PersistableBundle();
persistableBundle.putInt("value", 100);
persistableBundle.putString("url", "Quibbler.com");
builder.setExtras(persistableBundle);3、JobService
JobService是执行Job的服务,继承自Service,实现onStartJob(JobParameters )和onStopJob(JobParameters )方法。
public class MyJobService extends JobService {
/**
* 如果返回值是 false, 这个方法返回时任务已经执行完毕。
* 如果返回值是 true, 那么这个任务正要被执行,我们就需要开始执行任务。
* 当任务执行完毕时你需要调用 jobFinished(JobParameters params, boolean needsRescheduled)来通知系统
*/
@Override
public boolean onStartJob(JobParameters params) {
return false;
}
/**
* jobFinished 正常调用结束一个 job 时,也是不会调用
* 只有在该 job 没有被执行完,就被 cancel 掉的时候回调到
* 返回 true 表示会重新放到JobScheduler里重新安排调度,false 表示直接忽略
*/
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}因为是Service,所以需要在AndroidManifest中注册,必须要加上android.permission.BIND_JOB_SERVICE权限
<service
android:name=".service.MyJobService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />JobSchedule相关的使用就介绍到这里,至于原理,估计和IntentService继承Service一样都是系统内部封装好的,以后有时间再看看AOSP的源码了解一下。
相关资料:
Docs > JobService(Added in API level 21)">Android Developer > Docs > JobService
Docs > JobInfo">Android Developer > Docs > JobInfo

