## 3 JobScheduler工作原理:系统服务、JobInfo构建、执行回调、配额与节流 JobScheduler 是 Android 5.0(API 21)引入的系统级调度服务,用于在满足预定条件(如网络可用、设备空闲、充电中)时执行延迟任务。它运行在 `system_server` 进程内,通过 Binder 与客户端应用交互,是 Android 原生任务调度的基石。 ### 3.1 边界划分 | 层次 | 职责边界 | 对外接口 | |------|----------|----------| | **客户端应用** | 提交 `JobInfo`,监听 `JobService` 回调 | `JobScheduler.schedule()`、`JobService.onStartJob()` | | **系统服务** | 管理任务队列、条件监控、执行调度 | `android.app.job.JobScheduler` | | **底层驱动** | 电源、网络、电池等状态监听 | 系统广播 / `PowerManager`、`ConnectivityManager` | 核心边界:**应用只负责定义任务条件和处理逻辑,调度决策完全交给系统服务**,应用无法干涉何时执行(除非触发配额限制)。 ### 3.2 组件职责
组件所属模块职责
JobSchedulerServicesystem_server接收客户端请求,维护任务队列,触发条件匹配
JobStoresystem_server持久化存储待执行任务,重启后恢复
JobEnginesystem_server计算任务执行窗口,驱动调度决策
JobService应用进程应用侧回调接口,接收调度执行请求,返回是否继续执行
JobInfo.Builder应用进程构建任务描述对象(约束、延迟、重试策略)
关键点:JobScheduler 的调度引擎完全运行在系统服务中,应用被杀死后已提交的任务仍由系统保管(JobStore 持久化),这是与 Handler 或 AlarmManager 的本质区别。
### 3.3 数据流与控制流

典型数据流:

  1. 构建:应用通过 JobInfo.Builder 设置约束(网络类型、充电状态、空闲等)与执行延迟,提交给 JobScheduler.schedule()。
  2. 持久化:系统服务将任务写入 JobStore(基于 XML 文件的持久化)。
  3. 条件匹配:JobSchedulerService 监听系统广播(ConnectivityManager、BatteryManager、IdleController),当条件满足时触发任务调度。
  4. 执行回调:系统绑定应用的 JobService,调用 onStartJob()。应用在回调中执行实际工作,返回 true 表示需要持续运行(异步),返回 false 立即结束。
  5. 完成通知:应用完成工作后需显式调用 jobFinished() 告知系统,否则系统可能延迟后续调度。
下面是 JobScheduler 核心数据流与控制流的内联 SVG 图: JobScheduler 工作流程 Client App JobSchedulerService JobStore (持久化) JobEngine JobService (应用) 系统状态监听 说明:JobEngine 根据系统状态(网络、充电、空闲)及任务约束计算执行窗口,触发 JobService 回调。 > 附:客户端应用提交 JobInfo 的典型代码示例(仅作补充说明):
ComponentName serviceName = new ComponentName(context, MyJobService.class);
JobInfo jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
    .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
    .setRequiresCharging(true)
    .setOverrideDeadline(1000 * 60 * 30)  // 最长延迟30分钟
    .build();
JobScheduler scheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
### 3.4 选型权衡 | 特性 | JobScheduler | WorkManager | |------|--------------|-------------| | **系统底层** | 直接使用系统服务 | 封装 JobScheduler + AlarmManager + 自定义执行器 | | **API 稳定性** | 依赖系统版本,Android 8+ 行为变化大 | 兼容到 API 14,行为统一 | | **配额控制** | 严格:每 15 分钟最多 10 个任务,每小时最多 120 个 | 灵活:可通过配置绕过系统限制(如使用 ForegroundInfo) | | **生命周期** | 任务执行完自动结束,需手动通知 | 支持链式任务、延迟组合、观察结果 | **权衡结论:** 若只面向 Android 8+ 且业务场景简单,可直接使用 JobScheduler;需要兼容旧版或复杂编排时选择 WorkManager。 ### 3.5 风险点 1. **系统节流失效**:某些厂商 ROM 对 JobScheduler 施加额外限制,导致任务不被触发。 2. **配额耗尽**:高频短任务容易触发每日/每小时配额,后续任务被丢弃。 3. **重启恢复失效**:若 JobStore 损坏或系统更新,持久化任务可能丢失。 4. **空闲状态歧义**:`setRequiresDeviceIdle(true)` 在 Android 9+ 行为变化,容易误认为设备从不空闲。
典型坑: 在 Android 12+ 中,系统会限制 JobScheduler 在后台启动服务。若 JobService 的 onStartJob 中尝试 startService 可能被系统拦截,导致 ANR。
### 3.6 落地步骤 1. **定义 JobService 子类**:继承 `android.app.job.JobService`,实现 `onStartJob` 和 `onStopJob`。 2. **在 Manifest 中注册**:添加 ``。 3. **构建 JobInfo**:使用 `JobInfo.Builder` 设置唯一 ID、组件、约束和延迟。 4. **提交调度**:通过 `Context.getSystemService(JobScheduler.class)` 获取服务,调用 `schedule(jobInfo)`。 5. **处理回调**:在 `onStartJob` 中执行任务,若异步执行需返回 `true`,完成后调用 `jobFinished()`。 6. **监听系统变化**:可重写 `onStopJob` 处理任务被系统终止时的清理。 ### 3.7 验收标准 - 任务在指定约束满足时**非精确**触发(误差约 1~15 分钟,取决于系统负载)。 - 连续提交超过 10 个任务 / 15 分钟内,后续任务被拒绝,系统日志输出 `JobScheduler: Too many jobs pending`。 - 应用被杀死后重启,未执行的任务在 `JobStore` 中保留,约 5 分钟内恢复调度。 - 调用 `cancel(jobId)` 后任务不再执行。 - 使用 `adb shell dumpsys jobscheduler` 能查看当前已排程的任务状态。