JobScheduler简介

JobScheduler机制简析

1.概述

JobScheduler主要用于在未来某个时间下满足一定条件时触发执行某项任务的情况,那么可以创建一个JobService的子类,重写其onStartJob()方法来实现这个功能。

JobScheduler提供了接口来调度各种类型的工作,在应用进程中执行。

JobInfo里面包含了很多关于工作的信息,可以将JobInfo传递给JobScheduler的schedule()方法。当声明的条件满足时,系统将会在应用进程中执行该工作。

当在创建JobInfo时,可以指定使用哪个JobService来执行工作。

Framework会知道你什么时候接收回调,并且尽可能尝试批量和延迟执行这些工作。典型的,如果你没有特别声明一个工作截止期限,那么工作将可能在任何时候被执行,这个依赖于JobScheduler内部队列的当前状态。然而,工作也可能被延迟到下一次设备连接到电源时执行。

JobScheduler不能直接初始化,而应该通过Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)方法获取。

JobScheduler的定义如下:

public abstract class JobScheduler {
    /*
    * schedule(JobInfo)的返回值;
    * 当输入参数无效时,则返回RESULT_FAILURE。这种情况会出现在工作执行时间太短了,或者系统不能解析JobService服务。
    */
    public static final int RESULT_FAILURE = 0;
    /*
    * schedule(JobInfo)的返回值;
    * 如果该工作被成功执行后,返回RESULT_SUCCESS。
    */
    public static final int RESULT_SUCCESS = 1;

    public abstract int schedule(JobInfo job);

    public abstract int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag);

    public abstract void cancel(int jobId);

    public abstract void cancelAll();

    public abstract @NonNull List<JobInfo> getAllPendingJobs();

    public abstract @Nullable JobInfo getPendingJob(int jobId);
}

JobScheduler是一个抽象类,具体的实现类是JobSchedulerImpl类。

2.JobScheduler服务的初始化

JobScheduler服务的启动是从SystemServer的startOtherServices()方法开始的。

private void startOtherServices() {
    ......
    mSystemServiceManager.startService(JobSchedulerService.class);
    ......
}

JobSchedulerService服务继承自SystemService服务,在被启动的时候,会执行onStart()方法。

2.1 SystemServiceManager.startService()

public <T extends SystemService> T startService(Class<T> serviceClass) {
    try {
        final String name = serviceClass.getName();

        // Create the service.
        ......
        final T service;
        try {
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            service = constructor.newInstance(mContext);//获取构造器
        } catch (InstantiationException ex) {
            ......
        }

        // Register it.
        mServices.add(service);

        // Start it.
        try {
            service.onStart();//调用服务的onStart()方法
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + name
                    + ": onStart threw an exception", ex);
        }
        return service;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }
}

可以看到,SystemServiceManager的startService()方法的主要作用是创建一个服务对象实例,并调用服务对象实例的onStart()方法。

2.2 JobSchedulerService.onStart()

public void onStart() {
    publishLocalService(JobSchedulerInternal.class, new LocalService());//将JobSchedulerService里的LocalService发布到本地服务中,只能被system进程访问该服务
    publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);//发布jobscheduler服务,这样其他服务和应用可以访问该服务
}

在onStart()方法中,主要是完成以下两件事情:

  1. 将JobSchedulerService里的LocalService发布到本地服务中,该服务只能被system进程访问;
  2. 将jobscheduler服务发布到SystemManager中,这样其他服务和应用可以访问该服务。

LocalService对应的实现如下:

final class LocalService implements JobSchedulerInternal {

    /**
     * Returns a list of all pending jobs. A running job is not considered pending. Periodic
     * jobs are always considered pending.
     */
    @Override
    public List<JobInfo> getSystemScheduledPendingJobs() {
        synchronized (mLock) {
            final List<JobInfo> pendingJobs = new ArrayList<JobInfo>();
            mJobs.forEachJob(Process.SYSTEM_UID, new JobStatusFunctor() {
                @Override
                public void process(JobStatus job) {
                    if (job.getJob().isPeriodic() || !isCurrentlyActiveLocked(job)) {
                        pendingJobs.add(job.getJob());
                    }
                }
            });
            return pendingJobs;
        }
    }
}

LocalService实现了JobSchedulerInternal接口,主要是返回所有待处理的工作。该服务是添加到本地服务列表中的,只能被system进程访问。

jobscheduler服务对应的实现是mJobSchedulerStub,它是在构建JobSchedulerService服务时被初始化的。

2.3 JobSchedulerService()

public JobSchedulerService(Context context) {
    super(context);
    mHandler = new JobHandler(context.getMainLooper());//构建一个主线程的Handler
    mConstants = new Constants(mHandler);
    mJobSchedulerStub = new JobSchedulerStub();//初始化JobSchedulerStub
    mJobs = JobStore.initAndGet(this);//初始化JobStore,见2.4

    // Create the controllers.
    mControllers = new ArrayList<StateController>();
    mControllers.add(ConnectivityController.get(this));//创建连接状态Controller
    mControllers.add(TimeController.get(this));//创建时间Controller
    mControllers.add(IdleController.get(this));//创建空闲Controller
    mControllers.add(BatteryController.get(this));//创建电池状态Controller
    mControllers.add(AppIdleController.get(this));//创建应用空闲Controller
    mControllers.add(ContentObserverController.get(this));
    mControllers.add(DeviceIdleJobsController.get(this));//创建设备空闲Controller
}

JobSchedulerStub继承了IJobScheduler.Stub类,作为实现接口IJobScheduler的binder服务端。

2.4 JobStore.initAndGet()

static JobStore initAndGet(JobSchedulerService jobManagerService) {
    //单例模式
    synchronized (sSingletonLock) {
        if (sSingleton == null) {
            sSingleton = new JobStore(jobManagerService.getContext(),
                    jobManagerService.getLock(), Environment.getDataDirectory());//见2.5
        }
        return sSingleton;
    }
}

JobStore的构造采取的是单例模式,全局只会创建一个对象实例。

2.5 JobStore()

private JobStore(Context context, Object lock, File dataDir) {
    mLock = lock;
    mContext = context;
    mDirtyOperations = 0;

    File systemDir = new File(dataDir, "system");//system目录
    File jobDir = new File(systemDir, "job");//job目录
    jobDir.mkdirs();
    mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"));// 创建一个jobs.xml文件

    mJobSet = new JobSet();//创建一个JobSet对象

    readJobMapFromDisk(mJobSet);//见2.6
}

在构造JobStore的时候,会创建一个jobs.xml文件,并创建一个JobSet对象,里面保存的是一个JobStatus的集合,最后将磁盘中的数据读取到JobSet对象中。这里的mJobsFile就是/data/system/job/jobs.xml。

2.6 JobStore.readJobMapFromDisk()

public void readJobMapFromDisk(JobSet jobSet) {
    new ReadJobMapFromDiskRunnable(jobSet).run();
}

@Override
public void run() {
    try {
        List<JobStatus> jobs;
        FileInputStream fis = mJobsFile.openRead();//打开JobsFile
        synchronized (mLock) {
            jobs = readJobMapImpl(fis);//借助XmlPullParser,从输入文件流中读取Job状态信息
            if (jobs != null) {
                for (int i=0; i<jobs.size(); i++) {
                    this.jobSet.add(jobs.get(i));//将JobStatus添加到JobSet中
                }
            }
        }
        fis.close();
    } catch (FileNotFoundException e) {
       ......
    }
}

readJobMapFromDisk方法主要是将磁盘文件中的Job状态信息读取到内存中,并通过XmlPullParser解析xml文件信息,将Job相关信息逐步封装成JobInfo——>JobStatus——>JobStore,最后保存在JobSchedulerService服务中。

在JobSchedulerService中保存了与工作相关的JobStore,然后JobStore又保存了JobSet,在JobSet中保存了一个JobStatus的集合,在每个JobStatus中都有一个JobInfo,在JobInfo里面保存了与工作相关的信息,例如jobId,service。他们之间的类图关系如下:

JobInfo类图

在创建JobSchedulerService的时候,初始化了7个StateController,这些Controller分别控制不同触发条件。

public abstract class StateController {
    protected final Context mContext;
    protected final Object mLock;
    protected final StateChangedListener mStateChangedListener;

    public StateController(StateChangedListener stateChangedListener, Context context,
        Object lock) {
        mStateChangedListener = stateChangedListener;
        mContext = context;
        mLock = lock;
    }
    ......
}

以ConnectivityController为例,来描述Controller的初始化过程。

2.7 ConnectivityController.get()

public static ConnectivityController get(JobSchedulerService jms) {
    synchronized (sC
  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JobScheduler是Android中的一个调度框架,它可以用来在特定的时间间隔或特定的条件下执行任务,同时也可以用来保持应用的活跃状态。 在Android系统中,应用程序在后台运行时有一定概率被系统回收释放内存,为了提高应用的用户体验和功能完整性,我们可以使用JobScheduler来保活应用。 具体实现方法如下: 1. 在AndroidManifest.xml文件中注册JobService,用于执行任务和保活应用。设置jobService的权限,以及设置该service的处理逻辑。 2. 在需要保活的地方调用JobScheduler的schedule()方法,创建一个JobInfo对象,并设置好相关参数。其中包括指定要执行的JobService、执行的触发条件(如设备空闲时、特定时间间隔、特定网络状态等)、设置重试或重复执行等。 3. 通过JobScheduler.schedule()方法将JobInfo对象提交给系统进行调度。系统会根据设置的条件和触发机制来执行任务。 需要注意的是,JobScheduler的保活机制是通过系统的调度来实现的,并不能保证100%的成功保活。因为在一些特殊的情况下,如低内存、电池低、系统启动等情况下,系统可能会暂停或取消JobScheduler的任务。所以我们还需要配合其他的保活机制来提高保活的成功率,如使用前台服务、双进程守护、自启动、推送等。 总结起来,JobScheduler是Android系统提供的一种调度框架,可以在一定程度上保活应用。通过设置JobInfo的相关参数,然后由系统进行调度执行,以确保应用的持续运行和活跃状态。同时,为了提高保活的成功率,我们还需要结合其他的保活机制来综合应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值