Android 9.0 JobScheduler(一) JobScheduler的使用

1.JobScheduler简介

JobScheduler是一个系统提供的框架,旨于在应用进程、而非系统进程内执行各种作业调度,其原理是启动通过bindservice的方式启动对应应用进程的service,并在Service中进行作业。在执行一个Job时,将会使得系统持有一个WakeLock锁,以防止系统休眠进入Suspend。

在创建一个作业时,会设置多个约束条件,比如可以指定特定的网络、是否只在充电时执行作业等,JobScheduler框架会根据这些约束条件,智能地执行作业,并尽可能对作业进行批操作和推迟,以防止频繁唤醒系统而影响功耗,还可以指定该Job的执行的截至期限。如果不指定一个作业的截至期限,那么该作业可能会在任意一个时刻运行,这取决于JobScheduler的内部队列。

2.JobScheduler组件

JobScheduler的使用比较简单,JobScheduler框架为应用提供了如下四个组件,通过这四个类的API可以让用户在应用中创建一个作业,并让系统对他进行调度。

  • 1.JobScheduler

JobScheduler类负责将应用需要执行的作业发送给框架,以准备对该应用Job的调度。JobScheduler是一个系统服务,可通过如下方式获取:

JobScheduler mJobScheduler = (JobScheduler) Context.getSystemService(Context.JOB_SCHEDULER_SERVICE). 
  • 2.JobInfo

JobInfo是传递给JobScheduler类的数据容器,它封装了针对调用应用程序调度作业所需的各种约束,也可以认为一个JobInfo对象对应一个作业,JobInfo对象通过JobInfo.Builder创建。它将作为参数传递给JobScheduler:

mJobScheduler.scheduler(mJobInfo);
  • 3.JobInfo.Builder

JobInfo.Builder是JobInfo的一个内部类,顾名思义,它就是用来创建JobInfo的Builder类。

JobInfo.Builder mBuilder = new JobInfo.Builder(id,new ComponentName(this,MyJobService.class));
mJobInfo = mBuilder.build();
  • 4.JobService

JobService是一个继承于Service的抽象类,他作为系统回调执行作业内容的终端,JobScheduler框架将通过bindService()方式来启动该服务.因此,用户必须在应用程序中创建一个JobService的子类,并实现其onStartJob()等回调方法,以及在清单文件中对它授予如下权限:

<service android:name=".MyJobService"
    android:permission="android.permission.BIND_JOB_SERVICE"/>

3.使用步骤

  • 1.创建一个JobService的子类,作为系统回调终端:
public class MyJobService extends JobService {

    @Override
    public boolean onStartJob(final JobParameters params) {
        return true;
    }
    @Override
    public boolean onStopJob(JobParameters params) {
        return false;//返回false表示停止后不再重试执行
    }
}

别忘了在清单文件中配置权限:

<service android:name=".MyJobService"
    android:permission="android.permission.BIND_JOB_SERVICE"/>
  • 2.创建JobInfo.Builder对象,为Job设置约束条件:
private ComponentName mServiceComponent;
//根据JobService创建一个ComponentName对象
mServiceComponent = new ComponentName(this, MyJobService.class);
JobInfo.Builder builder = new JobInfo.Builder(mJobId++, mServiceComponent);
builder.setMinimumLatency(1000);//设置延迟调度时间
builder.setOverrideDeadline(2000);//设置该Job截至时间,在截至时间前肯定会执行该Job
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);//设置所需网络类型
builder.setRequiresDeviceIdle(true);//设置在DeviceIdle时执行Job
builder.setRequiresCharging(true);//设置在充电时执行Job
builder.setExtras(extras);//设置一个额外的附加项
//...
  • 3.获取JobScheduler实例
JobScheduler mJobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
  • 4.开始调度Job
mJobScheduler.schedule(builder.build());//调度Job
mJobScheduler.cancel(jobId);//取消特定Job
mJobScheduler.cancelAll();//取消应用所有的Job

4.组件API

下面根据创建时机,对以上提到的四个组件类提供的API进行总结。

4.1.JobInfo.Builder

1.构造方法

JobInfo.Builder构造方法如下:

  • JobInfo.Builder (int jobId, ComponentName jobService)

    int jobId:指定一个jobId,该Id可用来取消Job等。
    ComponentName jobService:接收JobScheduler回调的终端ComponentName对象,应来自一个JobService对象。

2.成员方法

  • setBackoffCriteria (long initialBackoffMillis, int backoffPolicy)

设置重新调度Job的策略
initialBackoffMillis:作业失败时最初等待的时间毫秒数;
backoffPolicy:重新执行一个job的执行策略

当调用JobService.JobFinished(params,true)、JobService.onStopJob()返回true时,都会根据该方法设置的策略重新调度.
对具有setRequiresDeviceIdle()的job设置该方法将引发异常。因为Doze状态下会对Job进行限制。

  • setEstimatedNetworkBytes (long downloadBytes, long uploadBytes)

设置该job将执行的网络流量大小。

  • setImportantWhileForeground (boolean importantWhileForeground)

设置该值为true,则说明该job在当app处于前台状态或白名单时是非常重要的。

  • setMinimumLatency (long minLatencyMillis)

指定此job按提供的时间延迟。在定期job上,调用次方法将引发异常。

  • setOverrideDeadline (longmJobScheduler maxExecutionDelayMillis)

设置此Job的最大延迟调度,无论任何条件,即使有条件不满足,Job也将在该截止时间前运行。在定期job上,调用次方法将引发异常。

  • setPeriodic (long intervalMillis)

设置该Job为定期Job,即按照提供的间隔时间周期执行,一个周期内最多执行一次,如果设置该方法,则setMinimumLatency()setOverrideDeadline()不可设置。

  • setPeriodic (long intervalMillis, long flexMillis)

指定此作业应按提供的间隔和弹性重新执行。作业可以在周期结束时在具有flex长度的窗口中随时执行。

  • setPersisted (boolean isPersisted)

设置是否在设备重新启动时保持此作业,此方法需要RECEIVE_BOOT_COMPLETED权限。

  • setPrefetch (boolean prefetch):
  • setRequiredNetwork (NetworkRequest networkRequest)

设置Job所需网络类型的详细描述,调用次方法后,将定义网络为该Job的严格要求,如果没有网络,那么该Job将不会执行。可以通过setOverrideDeadline()来更改此行为。

当Job在jobservice.onStartJob(jobParameters)中执行时,请确保使用jobParameters.getNetwork()返回的特定网络.

  • setRequiredNetworkType (int networkType)

设置Job所需网络类型的基本描述;

可选参数在JobInfo中,如:JobInfo.NETWORK_TYPE_UNMETERED

  • setRequiresBatteryNotLow (boolean batteryNotLow)

指定该Job是否只在非低电量时运行,默认为false,如果指定为true,那么该job将仅仅在非低电量模式下运行。默认为false。

  • setRequiresCharging (boolean requiresCharging)

指定该Job是否只在充电时运行此Job。默认为false。

  • setRequiresDeviceIdle (boolean requiresDeviceIdle)

指定该Job是否只在DeviceIdle状态时运行此Job,即在交互状态时将不会运行。默认为false。

  • setRequiresStorageNotLow (boolean storageNotLow)

指定此Job是否只在可用存储空间太低时运行,默认为false。

  • setTransientExtras (Bundle extras)

设置临时附加项;

  • setTriggerContentMaxDelay (long durationMs):
  • setExtras (PersistableBundle extras)

设置额外附加项,如果需要携带其他基本类型参数,可以通过这个方法设置。

  • build ()

创建JobInfo对象。

4.2.JobInfo

JobInfo中提供了几个用于方法参数的常量,以及和JobInfo.Builder中的setXXX()方法对应的getXXX()方法,此处就不再对这些方法进行说明,我们来看看它里面的一些常量的含义。

  • BACKOFF_POLICY_EXPONENTIAL

以指数形式重新调度job

  • BACKOFF_POLICY_LINEAR

以指数形式重新调度job

以上两常量作为JobInfo.Builder.setBackoffCriteria()的第二个参数使用,指定重新调度Job的策略。

  • DEFAULT_INITIAL_BACKOFF_MILLIS

当重新执行一个job时,默认退让毫秒数(30s),JobInfo.Builder.setBackoffCriteria()的第一个参数.

  • MAX_BACKOFF_DELAY_MILLIS

当重新执行一个job时,最大退让(延迟)毫秒数。

  • NETWORK_TYPE_ANY

设置该值时,表示对应Job需要网络连接

  • NETWORK_TYPE_CELLULAR

设置该值时,表示对应Job需要网络连接,且为蜂窝网络

  • NETWORK_TYPE_NONE

默认值,表示该Job对网络连接无要求

  • NETWORK_TYPE_NOT_ROAMING

设置该值时,表示对应Job需要网络连接,且为非漫游网络

  • NETWORK_TYPE_UNMETERED

设置该值时,表示对应Job需要网络连接,且为WIFI(非计量)

以上这些NETWORK_TYPE_XXX值,作为方法JobInfo.Builder.setRequiredNetworkType()的参数使用,用于指定一个Job是否需要特殊网络条件。

4.3.JobScheduler

1.实例化

在上面已经说过了,JobScheduler是一个系统服务,通过如下方式获取其实例:

Context.getSystemService(Context.JOB_SCHEDULER_SERVICE). 

2.成员方法

  • cancel (int jobId)

取消指定的Job,并将忽略JobService.onStopJob()的返回值。

  • cancelAll ()

取消该应用已调度的所有的Job。

  • int enqueue (JobInfo job, JobWorkItem work)

  • List getAllPendingJobs ()

获取应用程序已调度的所有Job。

  • JobInfo getPendingJob (int jobId)

查找指定Job的描述信息。

  • int schedule (JobInfo job)

开始调度一个Job,将使用JobInfo替换相同JobID中的所有信息,如果该Job正在运行,将会停止它。该方法返回值为RESULT_FAILURE or RESULT_SUCCESS,表示调度成功或失败。

3.常量

  • RESULT_FAILURE

在调用schedule()时,提供参数无效时将返回该值。

  • RESULT_SUCCESS

在调用schedule()时,如果成功调度将返回该值。

4.4.JobService

JobService是JobScheduler最终回调的端点,JobScheduler将会回调该类中的onStartJob()开始执行异步任务。该类是一个抽象类,用户必须继承JobScheduler实现一个类,并在配置文件中授予权限:

     <service android:name="MyJobService"
              android:permission="android.permission.BIND_JOB_SERVICE" >
         ...

1.成员函数

  • onStartJob (JobParameters params)

当Job开始执行时,将回调该方法,因此该方法中为所执行的内容,该方法执行在应用主线程中。当该方法执行完毕后,如果返回true,那么也就意味着Job将一直处于激活的状态,依旧持有WakeLock锁;如果返回false表示该Job完成后,将不会再继续进行,释放WakeLock锁。

如果返回true,有如下三种方式结束该Job的执行:
1.调用JobFinished()方法通知系统已经完成其工作;
2.调用cancel()方法取消该Job,此时将回调onStopJob()方法;
3.如果没有任何处理,JobSchedulerService中将在600s后回调onStopJob()方法,并在8s后结束该Job的执行。
因此,如果onStartJob()执行完毕后,不再需要重复执行,则返回值更推荐使用false,当执行完毕任务后,将立即释放WakeLock锁,从而更好地优化功耗。

  • onStopJob (JobParameters params)

如果在调用前JobFinished()系统停止该Job,则将回调该方法。比如在执行该Job过程中约束条件不满足导致停止了,这种情况下将回调该方法,然后将释放WakeLock锁。该方法返回true,则表示是否需要根据该Job创建时提供的重新执行策略重新调度该Job。返回false,则表示该job完全停止。

  • jobFinished (JobParameters params, boolean wantsReschedule)

params:job所携带的参数
wantsReschedule:是否需要重复执行

该方法需要用户手动调用,以通知作业调度器已经完成该Job工作,系统收到调用信息后,将释放执行外Job时的WakeLock锁。

参数wantsReschedule如果设置为true,将根据setBackbackOffCriteria()设置的执行策略进行调整。这种情况下,当重新调度作业时,最初的初始需求将被保留。

4.5.JobParamters

用来配置Job的参数容器,也就是说JobParamters有该Job的所有配置参数,因此它提供了多个getXXX()方法可以获取这些参数。JobParamters参数无需用户自行创建,系统将会创建完成,并作为JobService中回调函数的参数。

在JobService的onStartJob(JobParamters)onStopJob(JobParamters)中,JobParamters做为参数使用。

示例

Github:https://github.com/jeraon/jobscheduler

Google官方Sample:https://github.com/googlesamples/android-JobScheduler/#readme

你可能感兴趣的:(Android系统开发)