JobScheduler布置后台任务以及实现进程保活?
1.简介
在Android 5.0 提供了一套新的 JobScheduler
API,它允许您定义要在以后的某个时间或在指定的条件下(例如,当设备在充电时)异步运行的作业来优化电池寿命。
https://developer.android.com/reference/android/app/job/package-summary
https://developer.android.com/reference/android/app/job/JobScheduler
https://developer.android.com/reference/android/app/job/JobService
2.关键类
JobInfo 描述任务,包含各个参数.
JobScheduler 管理任务:布置、撤销、更新等.
JobService 执行任务的服务组件.
2.1 JobScheduler
int schedule (JobInfo job) |
布置一个任务,如果任务的id相同,后者覆盖前者,如果前者正在运行,它会被打断. 布置失败返回 RESULT_FAILURE ,可能job的参数有错误 布置成功返回RESULT_SUCCESS |
void cancel (int jobId) |
撤销指定id的任务,如果任务正在运行,它立刻停止.由于是用户手动撤销,所以任务的 onStopJob 的返回值没 有意义,被忽略. |
void cancelAll () |
撤销所有任务. |
int enqueue (JobInfo job,JobWorkItem work) |
布置任务和工作内容,如果该任务不存在,则添加一个新的任务.如果该任务正在运行,会被中断并以新的内容 添加到队列中. 如果jobInfo使用 使用JobInfo.Builder.setClipData(ClipData, int)添加数据后的任务永远被视为新任务,即使ClipData相同. |
JobInfo getPendingJob (int jobId) |
根据id查找任务. |
List<JobInfo> getAllPendingJobs () |
返回当前应用布置的所有任务.(包括已经启动的和等待中的) |
2.2 JobInfo及JobInfo.Builder
JobInfo.Builder 构造jobinfo,设置任务的各项参数.如网络类型,运行周期等.
JobInfo build () | 生成一个JobInfo对象 |
setBackoffCriteria (long initialBackoffMillis,int backoffPolicy) |
设置回退策略,与setRequiresDeviceIdle(boolean)冲突. initialBackoffMillis 是失败后的等待时间, backoffPolicy 是回退方式,有BACKOFF_POLICY_LINEAR 和 BACKOFF_POLICY_EXPONENTIAL 两种. |
setEstimatedNetworkBytes (long downloadBytes, long uploadBytes) |
预算任务网络连接时使用的字节数,如果知道具体字节最好,如果不是固定的可用JobInfo.NETWORK_BYTES_UNKNOWN |
setExtras (PersistableBundle extras) | 设置额外数据, PersistableBundle 里要放基本类型的数据. |
setImportantWhileForeground (boolean importantWhileForeground) |
是否临时加入白名单,在变成前台重要任务.默认false. 与setMinimumLatency、setOverrideDeadline、setPeriodic冲突。 |
setMinimumLatency (long minLatencyMillis) | 设置最小延迟时间,与 setPeriodic 冲突. |
setOverrideDeadline (long maxExecutionDelayMillis) | 最后执行期限,条件不满足也执行.与 setPeriodic 冲突. |
setPeriodic (long intervalMillis) | 设置任务执行周期,单位毫秒. |
setPeriodic (long intervalMillis, long flexMillis) | |
setPersisted (boolean isPersisted) | 设置是持久任务,开机后仍然有效. |
setPrefetch (boolean prefetch) | 设置任务是否预读本地内容,如果是,则系统会放宽网络类型约束. |
setRequiredNetwork (NetworkRequest networkRequest) |
设置任务使用的网络类型,如果无联网,不要调用这个方法,默认是null,这是一个非常严厉的约束,如果网络类型不满足, 任务不会被执行.这个方法有重载,只调用其中一个就可,重复调用后面的会覆盖前面的. 常用的类型:
|
setRequiredNetworkType (int networkType) | |
setRequiresBatteryNotLow (boolean batteryNotLow) | 是否只在非低电量情况下运行,true表示在非低电量运行,默认false. |
setRequiresCharging (boolean requiresCharging) | 设置是否只在充电时运行.默认fase.注意系统在特别繁忙时,可能忽略usb充电,这时任务不会被执行. |
setRequiresDeviceIdle (boolean requiresDeviceIdle) | 在空闲时运行,默认fase,这里的空闲状态是个宽泛的系统定义,通常指在没有应用与用户交互时. |
setRequiresStorageNotLow (boolean storageNotLow) | 非低存储空间时运行.默认false. |
setTransientExtras (Bundle extras) | 给任务添加临时数据,与setPersisted冲突. |
addTriggerContentUri (JobInfo.TriggerContentUri uri) |
添加内容触发器,监听某个内容,它变化后才执行这个任务,uri指定要被ContentObserver监听的内容,与setPeriodic(long) or setPersisted(boolean)冲突.如: 1 JobInfo.Builder builder = new JobInfo.Builder(JobIds.PHOTOS_CONTENT_JOB, 2 new ComponentName("com.example.android.apis", PhotosContentJob.class.getName())); 3 // Look for specific changes to images in the provider. 4 builder.addTriggerContentUri(new JobInfo.TriggerContentUri( 5 MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 6 JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS)); 7 // Also look for general reports of changes in the overall provider. 8 builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MEDIA_URI, 0)); 9 JOB_INFO = builder.build(); |
setTriggerContentMaxDelay (long durationMs) |
设置内容变化到任务被布置间的最大延迟(毫秒). |
setTriggerContentUpdateDelay (long durationMs) |
设置内容变化到任务被布置间的延迟(毫秒). If there are more changes during that time,the delay will be reset to start at the time of the most recent change. |
JobInfo常用的方法是一些get方法,如getRequiredNetwork () , getBackoffPolicy () , isPeriodic () 等.
2.3 JobService
以startService方式启动服务,其中几个重要方法:
boolean onStartJob (JobParameters params) |
当scheduler添加调度任务后,任务开始执行时产生这个回调,默认在主线程. 注意这个参数,它里面保存了传来的数据.通常要保存它,当任务完成时,手动调用jobFinished 时使用. 返回true表示任务在手动调用jobFinished结束或系统条件不满足而停止前一直在活跃状态, 服务断续运行,这时系统为这个任务保留wakelock锁.直到jobFinished或onStopJob调用. 返回false表示任务正常结束,这时系统会释放与这个任务关联的wakelock锁. 如果任务简短并且同步的那么应该返回false,如果异步的应用在任务完成后手动调用jobFinished |
boolean onStopJob (JobParameters params) |
来自系统的结束任务通知.通常在任务执行条件不能被满足时产生这个回调,如:当你在构造任务时 指定了网络条件是wifi,在任务执行期间你关掉了wifi. 注意:一定要处理这条信息,如释放不用的资源,否则应用会产生异常行为. 返回true表示你还希望在按照构造里指定的重试策略重试,当这个任务里有多条工作内容时, 要返回true,表示这个任务需要重新布置执行未完成的工作.. 返回false表示结束不重试,但是不管返回什么,当前这个任务必需停止. |
void jobFinished (JobParameters params, |
当任务完成后,手动调用这个方法通知系统任务完成,然后系统释放相应的wakelock锁, 第1个参数是 onStartJob 传来的参数. 第2个参数表示是否尝试回滚策略,如果是不得以要执行的这个方法,true表示按构造时指定的回滚 策略重新安排. 默认的回滚策略不会让任务在系统睡眠期间执行,而只是把它重新添加到任务队列中,在系统修整维护期间 才执行这个任务. |
3.实现进程保活?不可靠!
如果想用JobService实现进程保活,那么就得设置任务为周期任务,有几个问题,证明用它实现进程保活不可靠.
- 在最近应用列表点全部清除后,进程会被杀死,周期任务被停止.
- 在api小于24时,不支持周期任务,只能自己用timer实现,同时要求JobService这个服务组件开启重启功能,但是这个功能不在在所有系统上都能顺利进行,如在emui,和miui上都被拒绝.emui:
6-11 15:47:42.292 1494-13224/? I/HwPFWLogger: AppAutoStartupPolicy:prevent scheduleRestart service of package com.example.android.jobscheduler, serviceInfo com.example.android.jobscheduler.service.MyJobService 06-11 15:48:12.311 1494-1494/? I/HwPFWLogger: AppAutoStartupPolicy:prevent start package com.example.android.jobscheduler, serviceInfo com.example.android.jobscheduler.service.MyJobService by callerPid 1494, callerUid 1000, scene:jobService
miui:
06-11 16:45:05.849 1432-1443/system_process I/ActivityManager: Force stopping service ServiceRecord{bf9fd5e u0 com.example.android.jobscheduler/.service.MyJobService} 06-11 16:45:06.147 1432-1447/system_process I/AutoStartManagerService: MIUILOG- Reject service :Intent { cmp=com.example.android.jobscheduler/.service.MyJobService } userId : 0 uid : 10127
- 而api大于23时,最小周期是15分钟,这对于实时任务来说又有点长.
4.示例
4.1 相关权限
常用权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
必用权限:
<service android:name="MyJobService" android:permission="android.permission.BIND_JOB_SERVICE" > ... </service>
4.2 下载代码
https://gitee.com/xi/JobService.git