JobService概述
JobService用于执行一些需要满足特定条件但不紧急的后台任务,利用 JobScheduler 来执行这些特殊的后台任务来减少电量的消耗。开发者可以设定需要执行的任务JobService,以及任务执行的条件 JobInfo,JobScheduler 会将任务加入到队列。在特定的条件满足时 Android 系统会去批量的执行所有应用的这些任务,而非对每个应用的每个任务单独处理。这样可以减少设备被唤醒的次数。
主要运营场景:app服务保活,电量优化,在手机电量不能太低情况下推送,开启服务,延迟1分钟再推送。
机制原理
主要类似于Handle机制的实现,通过JobInfo.Builder生成JobInfo信息,然后JobSchedule通过JobInfo开启JobService
实例分析
步骤实现
- 写一个服务继承JobService
- 清单文件注册并且加权限android:permission=“android.permission.BIND_JOB_SERVICE”(如果JobService未申请权限或者申请的权限未被授予,系统将忽略该jobService的调度请求)
- JobInfo.Builder控制服务开启条件
- .Schedule(JobInfo)开启服务
JobService
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| package com.team308.mytest.jobService
import android.app.job.JobParameters import android.app.job.JobService import android.content.Intent import android.os.Build import android.os.Handler import android.os.Message import android.util.Log import androidx.annotation.RequiresApi
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) class MyJobService : JobService() {
companion object{ private const val TAG = "MyJobService" }
override fun onCreate() { Log.d(TAG, "onCreate") super.onCreate() } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Log.d(TAG, "onStartCommand" + super.onStartCommand(intent, flags, startId)) return super.onStartCommand(intent, flags, startId) }
override fun onUnbind(intent: Intent?): Boolean { Log.d(TAG, "onUnbind") return super.onUnbind(intent) }
override fun onDestroy() { Log.d(TAG, "onDestroy") super.onDestroy() } private val MESSAGE_ID_TASK = 0x01
private val mHandler = Handler { msg ->
jobFinished(msg.obj as JobParameters, false) true }
override fun onStartJob(params: JobParameters?): Boolean { Log.d(TAG, "onStartJob") val msg = Message.obtain( mHandler, MESSAGE_ID_TASK, params ) mHandler.sendMessage(msg) return true }
override fun onStopJob(params: JobParameters?): Boolean { Log.d(TAG, "onStopJob") mHandler.removeMessages(MESSAGE_ID_TASK) return false }
}
|
JobScheduleManager
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 43 44 45 46
| package com.team308.mytest.jobService import android.app.job.JobInfo import android.app.job.JobScheduler import android.content.ComponentName import android.content.Context import android.os.Build import androidx.annotation.RequiresApi @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) class JobScheduleManager() { constructor(con:Context) : this() { this.mContext = con mJobScheduler = con.getSystemService(JobScheduler::class.java) } companion object { private const val JOB_ID = 1 private var mJobManager: JobScheduleManager? = null fun getInstance(con: Context): JobScheduleManager { if (mJobManager == null) { mJobManager = JobScheduleManager(con) } return mJobManager as JobScheduleManager } } private var mJobScheduler: JobScheduler? = null private var mContext: Context? = null fun startJobScheduler(){ val builder = JobInfo.Builder( JOB_ID, ComponentName(mContext!!, MyJobService::class.java) ) builder.setPeriodic(30000) builder.setPersisted(true) builder.setRequiresCharging(true) val info = builder.build() mJobScheduler!!.schedule(info) } fun stopJobScheduler(){ mJobScheduler!!.cancelAll() } }
|
JobServiceActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package com.team308.mytest.jobService
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import com.team308.mytest.R
class JobServiceActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_job_service) JobScheduleManager.getInstance(this).startJobScheduler() } }
|
生命周期
1、可以看到Jobservice生命周期。开启到任务结束对应:
onCreate->onStartJob->onUnbind->onDestroy
2、你或许会疑问,为啥onStartCommand没有回调???job结束了onStopjob 没有回调???
1、为啥onStartCommand没有回调:通过观看jobservice源码你会发现其内部是通过bind方式开启的服务,所以不走onStartCommand,并且绑定服务由系统控制。
2、job结束了onStopjob 没有回调:因为这属于系统设计。这个方法是当service的条件不满足时系统回调,例如build设置需要网络,这时用户断开网络。这时就会回调。
重要api介绍
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
|
@Override public boolean onStartJob(JobParameters jobParameters) { Log.i(TAG, "onStartJob: "); return false; }
@Override public boolean onStopJob(JobParameters jobParameters) { Log.i(TAG, "onStopJob: ");
return false; }
|
JobInfo.Build 的重要API
setRequiredNetworkType 网络要求(例子JobInfo.NETWORK_TYPE_ANY表名需要有网)
setRequiresBatteryNotLow(true) 运行此job时,设备电量不能低
setRequiresCharging(true) 默认值为false。true表示此job需要在“充电”状态下工作。这里的充电可以理解为充电玩手机时,电量是增的。(假如你使用usb插在电脑上边充电边看视屏,电量可能冲着还减着)
setRequiresDeviceIdle(true) 设置设备在空闲的时候执行job,此条件一般很难达到。
setRequiresBatteryNotLow(true) 运行此job需要设备的可用存储空间不能太低。
builder.setPeriodic(5*1000) 设置的时间段内执行,执行不会超过一次。你不能控制执行的时间,仅仅能确定的是在设定的期间内job会执行一次。(安卓7.0开始这个值最小要设置15min否则15min内不起作用)
builder.setMinimumLatency(1000 * 5) 设置延迟的时间,在延迟时间到达之前不会考虑执行job(与setPeriodic一起使用会报异常)
builder.setOverrideDeadline(1000L10) 设置执行的最后期限,在最后期限到达之前会执行此job*(与setPeriodic一起使用会报异常)
JobSchedule常用API
scheduler.schedule(jobinfo) 开启jobservice
cancel(jobid) 结束指定id的service
cancelAll() 结束所有的service
JobInfo jobinfo = scheduler.getPendingJob(jobid) 根据 jobid 获取jobInfo对象
List allPendingJobs = scheduler.getAllPendingJobs() 获得所有的jobInfo
参考:https://blog.csdn.net/qq_38350635/article/details/106390343