Android8.0利用JobScheduler实现服务的运行

从Google Play要求所有应用最低的目标sdk版本为26开始,更改后台服务就被提上了日程。官方推荐的是使用JobScheduler,它可以根据指定的各种条件,更好的为用户处理网络相关的作业。当声明的条件满足时,由系统在应用进程中执行该工作。

JobScheduler+JobInfo+JobService

JobScheduler主要负责任务调度。JobInfo描述了任务的概要信息,传递给JobScheduler完全封装调度应用程序调度工作所需参数的数据容器。JobService则用来处理任务。JobScheduler是在API21中才有的,所以使用JobScheduler需要添加判断,在API>=21的时候,选择使用JobService的方式启动服务。具体的一些方法说明可以查阅官方文档,这里主要说明具体的用法。

创建JobInfo

  /**
     * 创建jobInfo
     * @param jobId 任务的标识符 唯一
     * @param componentName jobService类
     * @param requestInterval 请求间隔
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public JobInfo buildJobInfo(int jobId, ComponentName componentName, long requestInterval)
    {
        //代表一个任务 使用建造者模式建造
        JobInfo jobInfo;
        // Android7上,设置周期执行时间,会强制按照getMinPeriodMills阈值执行,此时设置任务执行最小时间间隔解决该问题
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
        {
            android.util.Log.d("jobService", "buildJobInfo: minimum");
            jobInfo = new JobInfo.Builder(jobId,componentName)
                    .setBackoffCriteria(requestInterval,JobInfo.BACKOFF_POLICY_LINEAR)//设置线性重试策略
                    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) //设置网络类型
                    .setMinimumLatency(requestInterval) //设置最小执行间隔
                    .setOverrideDeadline(requestInterval)//设置任务执行的最晚延迟时间
                    .setPersisted(true)//设置重启后任务是否保留
                    .build();
        }else {
            android.util.Log.d("jobService", "buildJobInfo: periodic");
            jobInfo = new JobInfo.Builder(jobId, componentName)
                    .setBackoffCriteria(requestInterval, JobInfo.BACKOFF_POLICY_LINEAR)//设置线性重试策略
                    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) //设置网络类型
                    .setPeriodic(requestInterval) //设置执行周期
                    .setPersisted(true)//设置重启后任务是否保留
                    .build();
        }
        return jobInfo;
    }
  • setBackoffCriteria(long initialBackoffMillis, int backoffPolicy)设置后退/重试策略。
    两种可选策略:
    BACKOFF_POLICY_EXPONENTIAL: 时间呈指数形式增长,默认值。
    BACKOFF_POLICY_LINEAR:时间呈线性形式增长
  • setMinimumLatency(long interval)设置最小的延迟时间和setOverrideDeadline(long interval)设置最大延迟时间,这两个方法不能和setPeriodic(long interval)一起使用

JobScheduler调度

    /**
     * 调度JobService
     */
    public void scheduleJobService(long requestInterval)
    {
        ComponentName jobName = new ComponentName(mMyAppliction,
                MonitorJobService.class);
       JobInfo jobInfo = buildJobInfo(JOB_HIGH_ID, highJobName,
                 requestInterval);
         if (mJobScheduler != null) {
             mJobScheduler.schedule(jobInfo);
         }
    }
    /**
     * 通过jobId取消对应的JobService
     * @param jobId
     */
    public void cancelJobServiceById(int jobId)
    {
        if(mJobScheduler != null)
        {
            android.util.Log.d("jobService", "cancelJobServiceById: " + jobId);
            mJobScheduler.cancel(jobId);
            //mJobScheduler.cancelAll()取消所有正在运行的服务
        }
    }

实现JobService类

public class MonitorJobService extends JobService {

    /**
     * @param params Parameters specifying info about this job, including the extras bundle you
     *               optionally provided at job-creation time.
     * @return True if your service needs to process the work (on a separate thread). False if
     * there's no more work to be done for this job.
     */
    @Override
    public boolean onStartJob(JobParameters params) {
        android.util.Log.d(TAG, "onStartJob: start");
        //在这里写处理逻辑的代码,如果需要做耗时处理则需要开启线程,在线程中做处理
        new MonitorAsyncTask().execute(params);
        //返回true说明工作还未完成,工作完成后需要通过JobFinished方法来通知系统
        return true;
    }
    /**
     * @param params Parameters specifying info about this job.
     * @return True to indicate to the JobManager whether you'd like to reschedule this job based
     * on the retry criteria provided at job creation-time. False to drop the job. Regardless of
     * the value returned, your job must stop executing.
     */
    @Override
    public boolean onStopJob(JobParameters params) {
        android.util.Log.d(TAG, "onStopJob: running");
        return false;
    }
    //AsyncTask处理耗时操作
    private class MonitorAsyncTask extends AsyncTask<JobParameters,Void,String>{
         private JobParameters mJobParameters;
        /**
         *
         * @param jobParameters The parameters of the task.
         * @return A result, defined by the subclass of this task.
         * @see #onPreExecute()
         * @see #onPostExecute
         * @see #publishProgress
         */
        @Override
        protected String doInBackground(JobParameters... jobParameters) {
            android.util.Log.d(TAG, "doInBackground: running");
            mJobParameters = jobParameters[0];
            //耗时操作
            return null;
        }
        //完成之后的处理工作
        @Override
        protected void onPostExecute(String s) {
            android.util.Log.d(TAG, "onPostExecute: running");
            super.onPostExecute(s);
            //如果不调用此方法,任务只会执行一次
            jobFinished(mJobParameters,false); 
        }
    }
}
  • JobFinished(JobParameter params,boolean needsReschedule)
    params:指定系统提供的有关此作业的信息,指向onStartJob(JobParameters)中的params.
    needsReschedue:返回true表示工作应该根据选定的重试策略(在创建JobInfo时指定的BACK_OFF_POLICY,返回false,则不需要。

最后,不要忘记在AndroidManifest.xml文件对应jobService声明中添加BIND_JOB_SERVICE的权限

<service
     android:name=".service.MonitorJobServiceNormal"
     android:enabled="true"
     android:permission="android.permission.BIND_JOB_SERVICE">
 service>

其他方法及优秀的库推荐

  • JobIntentService,JobScheduler,JobInfo,JobService的一套机制是比较繁琐的,而且只在API21上有用。所以官方又推出了JobIntentService来帮助我们简化步骤,实现兼容。Android8.0以上被当做普通的Intent使用startService()启动service来执行,8.0以上则用来作为Job来执行。但是复杂也有复杂的好处,我们可以指定service的相关条件,所有根据条件决定到底使用哪种方式。
  • FireBase JobScheduler:https://github.com/firebase/firebase-jobdispatcher-android
    github上封装好的一个库,兼容到API14,但是需要Google Play的支持,比较适合国外开发的app使用。
  • evernote/android-job :https://github.com/evernote/android-job
    同样的封装好的一个库,兼容到API14,不需要Google play的支持。

你可能感兴趣的:(Android)