作业调度:JobSchedule

QuibblerQuibbler 2020-10-08 约 18 分钟 1549 次阅读

作业调度:JobSchedule

Android中有很多定时任务,比如定时后台更新数据,使用AlarmManager设置(详见AlarmManager定时任务)。但是这些往往会很耗电,如果偷偷的直接执行任务,用户的电量不知不觉的没了体验很不好。推荐用Jetpack中的Jetpack定时任务利器:WorkManager!

1、JobSchedule

从API Level 21加入的JobSchedule任务调度可以设定一些执行条件,比如充电、WiFi网络等条件下才执行相应的任务。解决上面那些耗电问题。

学习标准的JobSchedule使用,可以参照Google Demo :googlearchive/android-JobScheduler

1.1、介绍

JobSchedule是系统服务,在SystemServer系统服务启动的过程中在startOtherServices()中创建初始化系统服务(见AMS服务的启动)。

/**
     * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
     */
    private void startOtherServices() {
        final Context context = mSystemContext;
        ...
        traceBeginAndSlog("StartJobScheduler");
        mSystemServiceManager.startService(JobSchedulerService.class);
        traceEnd();
        ...
    }

1.2、获取实例

虽然JobSchedule的构造函数并不是private,理论上可以用构造函数创建JobSchedule实例(实现一堆抽象方法)。但是最好使用Context从系统服务集合中获取实例,而不是直接通过构造函数实例化。

JobScheduler jobSchedule = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);

1.3、方法

①cancel(int jobId):取消指定jobID的任务

②cancelAll():取消所有本应用的调度任务

③int enqueue(JobInfo job, JobWorkItem work):和schedule(JobInfo job)相似

④List<JobInfo> getAllPendingJobs():获取应用安排的所有任务

⑤JobInfo getPendingJob(int jobId):查找指定jobID的任务

⑥int schedule(JobInfo job):计划任务(如果已成功安排此作业,则从返回RESULT_SUCCESS)。替换相同ID的作业,如果作业正在执行则会停止

此外还定义了两个任务执行结果的常量RESULT_SUCCESS和RESULT_FAILURE,分别代表任务执行成功和失败。

/** @hide */
    @IntDef(prefix = { "RESULT_" }, value = {
            RESULT_FAILURE,
            RESULT_SUCCESS,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Result {}
    /**
     * Returned from {@link #schedule(JobInfo)} when an invalid parameter was supplied. This can occur
     * if the run-time for your job is too short, or perhaps the system can't resolve the
     * requisite {@link JobService} in your package.
     */
    public static final int RESULT_FAILURE = 0;
    /**
     * Returned from {@link #schedule(JobInfo)} if this job has been successfully scheduled.
     */
    public static final int RESULT_SUCCESS = 1;

2、JobInfo

作为schedule(JobInfo job)方法的参数,JobInfo封装了任务所需的所有信息。

2.1、JobInfo.Builder

使用JobInfo.Builder构造JobInfo实例,先通过构造方法构造JobInfo.Builder实例,传入Job ID和需要执行JobInfo的JobService服务组件。

/**
     * 初始化一个新的Builder来构造一个JobInfo
     *
     * @param jobId Application-provided id for this job. Subsequent calls to cancel, or
     * jobs created with the same jobId, will update the pre-existing job with
     * the same id.  This ID must be unique across all clients of the same uid
     * (not just the same package).  You will want to make sure this is a stable
     * id across app updates, so probably not based on a resource ID.
     *
     * @param jobService The endpoint that you implement that will receive the callback from the
     * JobScheduler.
     */
    public Builder(int jobId, @NonNull ComponentName jobService) {
        mJobService = jobService;
        mJobId = jobId;
    }

2.2、添加条件

①Builder setRequiredNetworkType(int networkType):任务执行所需网络条件,有下面5种:

/** Default. */
    public static final int NETWORK_TYPE_NONE = 0;
    /** This job requires network connectivity. */
    public static final int NETWORK_TYPE_ANY = 1;
    /** This job requires network connectivity that is unmetered. */
    public static final int NETWORK_TYPE_UNMETERED = 2;
    /** This job requires network connectivity that is not roaming. */
    public static final int NETWORK_TYPE_NOT_ROAMING = 3;
    /** This job requires network connectivity that is a cellular network. */
    public static final int NETWORK_TYPE_CELLULAR = 4;

②Builder setRequiredNetwork(NetworkRequest networkRequest)

③Builder setEstimatedNetworkBytes(long networkBytes):预估该Job下载所用流量

④Builder setEstimatedNetworkBytes(long downloadBytes,long uploadBytes):预估预估该Job下载、上传所用流量

⑤Builder setRequiresCharging(boolean requiresCharging):任务执行需要在充电条件下

⑥Builder setRequiresBatteryNotLow(boolean batteryNotLow):需要电池电量不低,具体什么标准,电量百分之几就不得而知

⑦Builder setRequiresDeviceIdle(boolean requiresDeviceIdle):设备处理IDLE状态才能执行

⑧Builder setRequiresStorageNotLow(boolean storageNotLow):需要存储空间不低

2.3、调度相关

①Builder setTriggerContentMaxDelay(long durationMs)

②Builder setTriggerContentUpdateDelay(long durationMs)

③Builder setPrefetch(boolean prefetch):将此设置为true表示此工作旨在预取内容,从而对设备的特定用户的体验产生实质性的改善。 例如,获取当前用户感兴趣的头条新闻。

④Builder setPersisted(boolean isPersisted):设置是否在重新启动设备后继续执行此作业。

⑤Builder setPeriodic(long intervalMillis):每隔intervalMillis毫秒循环执行

⑥Builder setPeriodic(long intervalMillis, long flexMillis)

⑦Builder setOverrideDeadline(long maxExecutionDelayMillis):maxExecutionDelayMillis时间后条件还没有触发立即执行

⑧Builder setMinimumLatency(long minLatencyMillis):设置任务延迟执行,不能与setPeriodic()一起使用

⑨Builder setImportantWhileForeground(boolean importantWhileForeground)

        ⑩Builder setPriority(int priority):应用层无法调用

        ⑪Builder setFlags(int flags):应用层无法调用

2.4、携带数据

使用Builder setExtras(PersistableBundle extras)方法即可,PersistableBundle继承自BaseBundle,内部有ArrayMap<String, Object>类型的mMap成员变量,携带数据,只允许基本类型的成员变量。可以在JobService方法中的JobParameters参数取出相应的数据。

示例:

PersistableBundle persistableBundle = new PersistableBundle();
    persistableBundle.putInt("value", 100);
    persistableBundle.putString("url", "Quibbler.com");
    builder.setExtras(persistableBundle);

3、JobService

JobService是执行Job的服务,继承自Service,实现onStartJob(JobParameters )和onStopJob(JobParameters )方法。

public class MyJobService extends JobService {
        
        /**
         * 如果返回值是 false, 这个方法返回时任务已经执行完毕。
         * 如果返回值是 true, 那么这个任务正要被执行,我们就需要开始执行任务。
         * 当任务执行完毕时你需要调用 jobFinished(JobParameters params, boolean needsRescheduled)来通知系统
         */
        @Override
        public boolean onStartJob(JobParameters params) {
            return false;
        }
        
        /**
         * jobFinished 正常调用结束一个 job 时,也是不会调用
         * 只有在该 job 没有被执行完,就被 cancel 掉的时候回调到
         * 返回 true 表示会重新放到JobScheduler里重新安排调度,false 表示直接忽略
         */
        @Override
        public boolean onStopJob(JobParameters params) {
            return false;
        }
    }

因为是Service,所以需要在AndroidManifest中注册,必须要加上android.permission.BIND_JOB_SERVICE权限

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

JobSchedule相关的使用就介绍到这里,至于原理,估计和IntentService继承Service一样都是系统内部封装好的,以后有时间再看看AOSP的源码了解一下。

相关资料:

         Docs > JobScheduler(Added in API level 21)">Android Developer > Docs > JobScheduler(Added in API level 21)

         Docs > JobService(Added in API level 21)">Android Developer > Docs > JobService

         Docs > JobInfo">Android Developer > Docs > JobInfo

        GitHub > googlearchive/android-JobScheduler

        JobSchedule 的使用以及源码分析

        使用JobSchedule对任务进行合理排期

        JobScheduler的使用

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w