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.setExtras(PersistableBundle)等添加了附加数据,要保持它们一致,

使用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,这是一个非常严厉的约束,如果网络类型不满足,

任务不会被执行.这个方法有重载,只调用其中一个就可,重复调用后面的会覆盖前面的.

常用的类型:

NETWORK_TYPE_NONENETWORK_TYPE_ANYNETWORK_TYPE_UNMETEREDNETWORK_TYPE_NOT_ROAMING or NETWORK_TYPE_METERED

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,
boolean wantsReschedule)

    当任务完成后,手动调用这个方法通知系统任务完成,然后系统释放相应的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

 

posted @ 2018-09-17 20:47  f9q  阅读(1413)  评论(0编辑  收藏  举报