最近在做一个广告屏功能的项目,用户希望应用在被杀死的情况下能自动重启,那我当时就想到android进程保活的JobScheduler
一.什么是JobScheduler
JobScheduler 简单来说就是一个系统定时任务,在app达到一定条件时可以指定执行任务,且如果app被强迫终止,此前预定的任务还可执行。
二.JobScheduler API使用
首先确保我们的app在android 5.0系统以上。
1.创建JobSchedulerService
@TargetApi(21)
class JobSchedulerService: JobService() {
override fun onStartJob(params: JobParameters): Boolean {
// 返回false,系统假设这个方法返回时任务已经执行完毕;
// 返回true,系统假定这个任务正要被执行
return true
}
override fun onStopJob(params: JobParameters): Boolean {
return false
}
}
onStartJob 系统触发执行任务 就会调用 返回false 表示我们的任务已完成 返回true 系统会默认这是一个耗时任务,此时是任务在异步执行,且在我们完成任务后,必须执行jobFinished
onStopJob 当调用cancle(jobId),且onStartJob 返回true时 才会调用
在manifest中注册
2.创建JobScheduler
var mJobScheduler = ctxt.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
构建JobInfo对象,传递给JobSchedulerService
val builder = JobInfo.Builder(JOB_ID, ComponentName(mContext, JobSchedulerService::class.java))
builder.setPeriodic(5000)
setMinimumLatency(long minLatencyMillis) 表示任务在至少多长时间后执行,不能和setPeriodic 同时使用,否则报错
setOverrideDeadline(long maxExecutionDelayMillis) 表示任务在某段时间后必须执行 ,不能和setPeriodic 同时使用,否则报错
setPeriodic(long intervalMillis) 表示任务间隔多长时间执行
setBackoffCriteria(long initialBackoffMillis, int backoffPolicy) 设置等待多长时间执行,默认是10s,如果小于10s,按照10s算
setPersisted()表示重启后是否还要继续执行,此时需要声明权限RECEIVE_BOOT_COMPLETED
setRequiresCharging() 设置是否在充电时执行
执行任务
val info = builder.build()
//开始定时执行该系统任务
mJobScheduler.schedule(info)
三.使用经验
按照以上步骤使用,在android5.0 和6.0系统上可正常运行,但在7.0及以上系统 onstartJob 不会调用
阅读源码可知 原来是系统强制使用了最小时间minperiod =15分钟 ,那如果我们要设置小于15min,就只能通过setMinimumLatenc()了。我满怀激动去运行,结果发现onstartJob只执行了一次。所以要想在7.0以上系统 可以重复调用,可以在onstartJob 里取消前面的job,并新建新的JobScheduler对象,手动调用jobFinished(params, false)结束作业。
附上源码:
在首页使用JobSchedulerUtil.getJobSchedulerInstance(this).startJobScheduler()
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
class JobSchedulerUtil private constructor(ctxt: Context) {
private val mJobScheduler: JobScheduler
init {
mContext = ctxt
mJobScheduler = ctxt.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
}
@TargetApi(21)
fun startJobScheduler() {
// 如果JobService已经启动,取消之前的job
if (JobSchedulerService.isJobServiceAlive ) {
stopJobScheduler()
}
// 构建JobInfo对象,传递给JobSchedulerService
val builder = JobInfo.Builder(JOB_ID, ComponentName(mContext, JobSchedulerService::class.java))
//android7.0 及以上系统
if (Build.VERSION.SDK_INT >= 24) {
builder.setMinimumLatency(3000) //至少3s 才会执行
// builder.setOverrideDeadline(3000) //3s后一定会执行
// builder.setMinimumLatency(3000)
// //默认是10s,如果小于10s,也会按照10s来依次增加
// builder.setBackoffCriteria(10000, JobInfo.BACKOFF_POLICY_LINEAR);
} else {
builder.setPeriodic(5000)
}
// 当插入充电器,执行该任务
builder.setRequiresCharging(true)
val info = builder.build()
//开始定时执行该系统任务
mJobScheduler.schedule(info)
}
fun stopJobScheduler() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mJobScheduler.cancel(JOB_ID)
}
}
companion object {
private val JOB_ID = 1
private var mJobUtil: JobSchedulerUtil? = null
private lateinit var mContext: Context
fun getJobSchedulerInstance(ctxt: Context): JobSchedulerUtil{
if (mJobUtil== null) {
mJobUtil= JobSchedulerUtil(ctxt)
}
return mJobUtil as JobSchedulerUtil
}
}
}
@TargetApi(21)
class JobSchedulerService : JobService() {
private val mHandler = Handler(Handler.Callback { msg ->
/**
*执行你想做的 工作
*/
// 通知系统任务执行结束
if (Build.VERSION.SDK_INT >= 24) {
//android7.0 及以上使用 重新开启一个JobScheduler
JobSchedulerUtil.getJobSchedulerInstance(this).startJobScheduler()
jobFinished(msg.obj as JobParameters, true)
}else{
//5.0 6.0
jobFinished(msg.obj as JobParameters, false)
}
true
})
override fun onStartJob(params: JobParameters): Boolean {
jobServiceHave = true
//因为是子线程且jobFinished需要params,通过handler 传递
var msg = Message()
msg.obj=params
msg.what= JOB_TASK
mHandler.sendMessage(msg)
return true
}
override fun onStopJob(params: JobParameters): Boolean {
mHandler.removeMessages(JOB_TASK)
return false
}
companion object {
//标识这个服务已开启
private var jobServiceHave: Boolean? = false
val isJobServiceAlive: Boolean
get() = jobServiceHave!!
private val JOB_TASK = 10001
}
}