| 组件 | 所属模块 | 职责 |
|---|---|---|
JobSchedulerService | system_server | 接收客户端请求,维护任务队列,触发条件匹配 |
JobStore | system_server | 持久化存储待执行任务,重启后恢复 |
JobEngine | system_server | 计算任务执行窗口,驱动调度决策 |
JobService | 应用进程 | 应用侧回调接口,接收调度执行请求,返回是否继续执行 |
JobInfo.Builder | 应用进程 | 构建任务描述对象(约束、延迟、重试策略) |
关键点:JobScheduler 的调度引擎完全运行在系统服务中,应用被杀死后已提交的任务仍由系统保管(JobStore 持久化),这是与 Handler 或 AlarmManager 的本质区别。
### 3.3 数据流与控制流
典型数据流:
- 构建:应用通过
JobInfo.Builder设置约束(网络类型、充电状态、空闲等)与执行延迟,提交给JobScheduler.schedule()。 - 持久化:系统服务将任务写入
JobStore(基于 XML 文件的持久化)。 - 条件匹配:JobSchedulerService 监听系统广播(ConnectivityManager、BatteryManager、IdleController),当条件满足时触发任务调度。
- 执行回调:系统绑定应用的
JobService,调用onStartJob()。应用在回调中执行实际工作,返回true表示需要持续运行(异步),返回false立即结束。 - 完成通知:应用完成工作后需显式调用
jobFinished()告知系统,否则系统可能延迟后续调度。
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 中注册**:添加 `