最近Jobscheduler的使用不当导致不少问题,比如定时任务不生效或者冲突。归根结底是对Jobscheduler的使用不熟悉以及,其工作原理没有一个系统性的了解。本人也曾踩坑,所以下定决心好好熟悉Jobscheduler。
概述
在android开发中经常会有这样的需求,开发者需要在稍后的某个时间点或者满足某个特定的条件时去执行某个任务,例如当设备开始充电,或者网络状态连接到wifi状态时执行某些推送通知的任务,jobscheduler就是用来处理这类场景的任务。
Jobscheduler的android在5.0上针对于降低功耗而提出来的一种策略方案,自 Android 5.0 发布以来,JobScheduler 已成为执行后台工作的首选方式,其工作方式有利于用户。应用可以在安排作业的同时允许系统基于设备状态、电源和连接情况等具体条件进行优化。JobScheduler 可实现控制和简洁性,谷歌推出该机制是想要所有应用在执行后台任务时使用它。 在之前的版本上,没有Job 这个服务,客户端代码如果需要实现类似的需求,必须要在客户端代码用alarm ,network, battery等服务来多次判断条件,以实现此类需求,对于App 开发者来说,其实是一个比较麻烦和复杂的代码逻辑。而job 的出现,很大程度上把此类条件判断逻辑放到服务端去判断,当所有限制条件满足时候,客户端触发job
如何使用jobscheduler
应用如果想使用JobScheduler API的话,首先需要创建自己需要执行的任务信息,创建任务的方法在谷歌官方文档上已经有详细介绍,这里只是放出一个实例:
JobInfo updateJob = new JobInfo.Builder(UPDATEDB_JOB_ID, new ComponentName(context, TimedUpdateCleanUpDbJobService.class))
.setPeriodic(UPDATE_MIN_TIME)// 设置循环时间
.setPersisted(true)// 是否是持久化的job,如果是,开机后便会设置到系统中,需要RECEIVE_BOOT_COMPLETED权限
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED) // 需要非计费网络
.setRequiresDeviceIdle(true)//需要设备空闲
.build();
JobScheduler scheduler = getSystemService(Context.JOB_SERVICE);
scheduler.scheduler(updateJob);
上面的一个任务是在开机之后执行初始化的操作。其实并不需要延时1s,但是这里需要注意的一个点是JobScheduler所创建并执行的人物必须是带有条件限制的,不然是违背其初衷的,当你创建一个任务不做任何限制条件并且直接调用 scheduler.schedule(builder.build());去执行该任务是不可行的,会报以下的异常
java.lang.IllegalArgumentException: You're trying to build a job with no constraints, this is not allowed.
其次需要新建一个service,来继承JobService(与DreamService类似),而且必须重写其中的两个方法,分别是onStartJob(JobParameters params)和onStopJob(JobParameters params);
客户端job 的代码书写
public class MyJobService extends JobService {
public abstract boolean onStartJob(JobParameters params) { // 在任务开始执行时触发。返回false表示执行完毕,返回true表示需要开发者自己调用jobFinished方法通知系统已执行完成。
...
jobFinished();
}
public abstract boolean onStopJob(JobParameters params){ //在任务停止执行时触发。返回true 为重新调度,返回false 表示不会重新调度,job完全被停止了
...
}
}
当上面创建任务时执行到scheduler.schedule(builder.build()); 则开始准备执行任务,一旦设置满足条件,便会执行到onStartJob()方法,也就是在我们的任务应该具体事宜应该是放在onStartJob中去做的。
当任务执行完毕后要调用jobFinished()来通知系统。当系统受到一个cancel请求时会取消该任务(当该任务未执行将其在pending list删除,如果该任务正在执行则停止其任务)。
使用Jobscheduler还需要到AndroidManifest.xml中添加一个service节点让你的应用拥有绑定和使用这个JobService的权限。
<service android:name="com.example.apuser.jobtest.JobTestService"
android:permission="android.permission.BIND_JOB_SERVICE" />
这里需要重点注意的是:这个job service运行在你的主线程,这意味着你需要使用子线程,handler, 或者一个异步任务来运行耗时的操作以防止阻塞主线程。
常见接口解释:
setRequiresBatteryNotLow(boolean) //是否需要电量充足
setRequiresCharging(boolean) //是否需要充电默认false
setRequiresDeviceIdle(boolean) //是否需要设备空闲,设备空闲是指设备没有在使用并且已经有一段时间没使用了
addTriggerContentUri(TriggerContentUri) //监听指定ContentUri,改变时才会触发任务,和周期性和持续性任务不兼容
setPeriodic(long) //是否是周期性任务,intervalMillis是执行的周期,每个周期最多执行一次,和setMinimumLatency和setOverrideDeadline不兼容,flextime = intervaltime
setPeriodic(long intervalMillis, long flexMillis) // flex 时间为窗口时间。最小窗口时间为5分钟()
setMinimumLatency(long) // 设置任务至少延迟多少时间才执行
setOverrideDeadline(long) // 任务执行的截止时间,如果到了该截止时间,其他条件不满足也会被执行
setRequiresStorageNotLow(boolean) //设置任务需要存储空间充裕条件
setPriority(int) // 设置优先级。越大优先级越高
setPersisted(boolean) // 是否是持续性任务,如果是,开机后会继续执行,但需要RECEIVE_BOOT_COMPLETED权限
总结
JobScheduler 虽然是在5.0上新增加的一个新服务,但是从L到M,N以及最新的O 上,谷歌Android也是在重点推荐使用该功能,并且在Android O 上谷歌还推出了一套Android vitals 计划,旨在提高Android 系统的功耗,性能,以及稳定性等相关指标,在对功耗上提出来的建议便是,非精确性的定时任务建议使用Job来代替Alarm,能更加准确的满足条件的执行你想要执行的任务。在Android O上JobScheduler更加完善了其条件控制,加上了低存储,低电量策略下的job运行限制,这里将在后面job服务解析中继续提到
网友评论