JobScheduler 进程保活

最近在做一个广告屏功能的项目,用户希望应用在被杀死的情况下能自动重启,那我当时就想到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 不会调用

可以看到 ,在7.0 系统使用会出现 

 

JobScheduler 进程保活_第1张图片

阅读源码可知  原来是系统强制使用了最小时间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
    }
}

 

你可能感兴趣的:(android)