1# 延迟任务(ArkTS)
2
3## 概述
4
5### 功能介绍
6
7应用退至后台后,需要执行实时性要求不高的任务,例如有网络时不定期主动获取邮件等,可以使用延迟任务。当应用满足设定条件(包括网络类型、充电类型、存储状态、电池状态、定时状态等)时,将任务添加到执行队列,系统会根据内存、功耗、设备温度、用户使用习惯等统一调度拉起应用。
8
9### 运行原理
10
11**图1** 延迟任务实现原理
12![WorkScheduler](figures/WorkScheduler.png)
13
14应用调用延迟任务接口添加、删除、查询延迟任务,延迟任务管理模块会根据任务设置的条件(通过WorkInfo参数设置,包括网络类型、充电类型、存储状态等)和系统状态(包括内存、功耗、设备温度、用户使用习惯等)统一决策调度时机。
15
16当满足调度条件或调度结束时,系统会回调应用[WorkSchedulerExtensionAbility](../reference/apis-backgroundtasks-kit/js-apis-WorkSchedulerExtensionAbility.md)中 onWorkStart() 或 onWorkStop() 的方法,同时会为应用单独创建一个Extension扩展进程用以承载[WorkSchedulerExtensionAbility](../reference/apis-backgroundtasks-kit/js-apis-WorkSchedulerExtensionAbility.md),并给[WorkSchedulerExtensionAbility](../reference/apis-backgroundtasks-kit/js-apis-WorkSchedulerExtensionAbility.md)一定的活动周期,开发者可以在对应回调方法中实现自己的任务逻辑。
17
18
19### 约束与限制
20
21- **数量限制**:一个应用同一时刻最多申请10个延迟任务。
22
23- **执行频率限制**:系统会根据<!--RP1-->[设备使用信息统计](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-deviceUsageStatistics-sys.md)应用的活跃分组<!--RP1End-->,对延迟任务做分级管控,限制延迟任务调度的执行频率。<!--Del-->通过能效资源接口申请了WORK_SCHEDULER资源的应用,会被放在能效资源豁免分组中。<!--DelEnd-->
24
25  **表1** 应用活跃程度分组
26  | 应用活跃分组 | 延迟任务执行频率 |
27  | -------- | -------- |
28  | 活跃分组 | 最小间隔2小时 |
29  | 经常使用分组 | 最小间隔4小时 |
30  | 常用使用 | 最小间隔24小时 |
31  | 极少使用分组 | 最小间隔48小时 |
32  | 受限使用分组 | 禁止 |
33  | 从未使用分组 | 禁止 |<!--Del-->
34  | 能效资源豁免分组 | 不受限制 |<!--DelEnd-->
35
36- **超时**:WorkSchedulerExtensionAbility单次回调最长运行2分钟。如果超时不取消,系统会终止对应的Extension进程。<!--Del-->对于系统特权应用,可以通过能效资源接口申请WORK_SCHEDULER资源,扩展单次回调运行时长,扩展后在充电状态下为20分钟,非充电状态下为10分钟。<!--DelEnd-->
37
38- **调度延迟**:系统会根据内存、功耗、设备温度、用户使用习惯等统一调度,如当系统内存资源不足或温度达到一定挡位时,系统将延迟调度该任务。
39
40- **WorkSchedulerExtensionAbility接口调用限制**:为实现对WorkSchedulerExtensionAbility能力的管控,在WorkSchedulerExtensionAbility中限制以下接口的调用:
41
42  [@ohos.resourceschedule.backgroundTaskManager (后台任务管理)](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-backgroundTaskManager.md)
43
44  [@ohos.backgroundTaskManager (后台任务管理)](../reference/apis-backgroundtasks-kit/js-apis-backgroundTaskManager.md)
45
46  [@ohos.multimedia.camera (相机管理)](../reference/apis-camera-kit/js-apis-camera.md)
47
48  [@ohos.multimedia.audio (音频管理)](../reference/apis-audio-kit/js-apis-audio.md)
49
50  [@ohos.multimedia.media (媒体服务)](../reference/apis-media-kit/js-apis-media.md)
51
52
53## 接口说明
54
55**表2** 延迟任务主要接口
56
57以下是延迟任务开发使用的相关接口,更多接口及使用方式请见[延迟任务调度](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-workScheduler.md)文档。
58| 接口名 | 接口描述 |
59| -------- | -------- |
60| startWork(work: WorkInfo): void; | 申请延迟任务 |
61| stopWork(work: WorkInfo, needCancel?: boolean): void; | 取消延迟任务 |
62| getWorkStatus(workId: number, callback: AsyncCallback&lt;WorkInfo&gt;): void; | 获取延迟任务状态(Callback形式) |
63| getWorkStatus(workId: number): Promise&lt;WorkInfo&gt;; | 获取延迟任务状态(Promise形式) |
64| obtainAllWorks(callback: AsyncCallback\<Array\<WorkInfo>>): void; | 获取所有延迟任务(Callback形式) |
65| obtainAllWorks(): Promise&lt;Array&lt;WorkInfo&gt;&gt;; | 获取所有延迟任务(Promise形式) |
66| stopAndClearWorks(): void; | 停止并清除任务 |
67| isLastWorkTimeOut(workId: number, callback: AsyncCallback\<boolean>): void; | 获取上次任务是否超时(针对RepeatWork,Callback形式) |
68| isLastWorkTimeOut(workId: number): Promise&lt;boolean&gt;; | 获取上次任务是否超时(针对RepeatWork,Promise形式) |
69
70**表3** WorkInfo参数
71| 名称             | 类型                                | 必填   | 说明               |
72| --------------- | --------------------------------- | ---- | ---------------- |
73| workId          | number                            | 是    | 延迟任务ID。          |
74| bundleName      | string                            | 是    | 延迟任务所在应用的包名。           |
75| abilityName     | string                            | 是    | 包内ability名称。 |
76| networkType     | [NetworkType](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-workScheduler.md#networktype)       | 否    | 网络类型。             |
77| isCharging      | boolean                           | 否    | 是否充电。<br>- true表示充电触发延迟回调,false表示不充电触发延迟回调。|
78| chargerType     | [ChargingType](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-workScheduler.md#chargingtype)     | 否    | 充电类型。             |
79| batteryLevel    | number                            | 否    | 电量。              |
80| batteryStatus   | [BatteryStatus](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-workScheduler.md#batterystatus)   | 否    | 电池状态。             |
81| storageRequest  | [StorageRequest](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-workScheduler.md#storagerequest) | 否    | 存储状态。             |
82| isRepeat        | boolean                           | 否    | 是否循环任务。<br>- true表示循环任务,false表示非循环任务。 |
83| repeatCycleTime | number                            | 否    | 循环间隔,单位为毫秒。             |
84| repeatCount     | number                            | 否    | 循环次数。             |
85| isPersisted     | boolean                           | 否    | 注册的延迟任务是否可保存在系统中。<br>- true表示可保存,即系统重启后,任务可恢复。false表示不可保存。|
86| isDeepIdle      | boolean                           | 否    | 是否要求设备进入空闲状态。<br>- true表示需要,false表示不需要。   |
87| idleWaitTime    | number                            | 否    | 空闲等待时间,单位为毫秒。           |
88| parameters      | [key: string]: number \| string \| boolean  | 否    | 携带参数信息。 |
89
90WorkInfo参数用于设置应用条件,参数设置时需遵循以下规则:
91
92- workId、bundleName、abilityName为必填项,bundleName需为本应用包名。
93
94- 携带参数信息仅支持number、string、boolean三种类型。
95
96- 至少设置一个满足的条件,包括网络类型、充电类型、存储状态、电池状态、定时状态等。
97
98- 对于重复任务,任务执行间隔至少2小时。设置重复任务时间间隔时,须同时设置是否循环或循环次数中的一个。
99
100**表4** 延迟任务回调接口
101
102以下是延迟任务回调开发使用的相关接口,更多接口及使用方式请见[延迟任务调度回调](../reference/apis-backgroundtasks-kit/js-apis-WorkSchedulerExtensionAbility.md)文档。
103| 接口名 | 接口描述 |
104| -------- | -------- |
105| onWorkStart(work: workScheduler.WorkInfo): void | 延迟调度任务开始的回调 |
106| onWorkStop(work: workScheduler.WorkInfo): void | 延迟调度任务结束的回调 |
107
108
109## 开发步骤
110
111延迟任务调度开发步骤分为两步:实现延迟任务调度扩展能力、实现延迟任务调度。
112
1131. **延迟任务调度扩展能力**:实现WorkSchedulerExtensionAbility开始和结束的回调接口。
114
1152. **延迟任务调度**:调用延迟任务接口,实现延迟任务申请、取消等功能。
116
117### 实现延迟任务回调拓展能力
118
1191. 新建工程目录。
120
121   在工程entry Module对应的ets目录(./entry/src/main/ets)下,新建目录及ArkTS文件,例如新建一个目录并命名为WorkSchedulerExtension。在WorkSchedulerExtension目录下,新建一个ArkTS文件并命名为WorkSchedulerExtension.ets,用以实现延迟任务回调接口。
122
1232. 导入模块。
124
125   ```ts
126   import { WorkSchedulerExtensionAbility, workScheduler } from '@kit.BackgroundTasksKit';
127   ```
128
1293. 实现WorkSchedulerExtension生命周期接口。
130
131   ```ts
132   export default class MyWorkSchedulerExtensionAbility extends WorkSchedulerExtensionAbility {
133     // 延迟任务开始回调
134     onWorkStart(workInfo: workScheduler.WorkInfo) {
135       console.info(`onWorkStart, workInfo = ${JSON.stringify(workInfo)}`);
136       // 打印 parameters中的参数,如:参数key1
137       // console.info(`work info parameters: ${JSON.parse(workInfo.parameters?.toString()).key1}`)
138     }
139
140     // 延迟任务结束回调
141     onWorkStop(workInfo: workScheduler.WorkInfo) {
142       console.info(`onWorkStop, workInfo is ${JSON.stringify(workInfo)}`);
143     }
144   }
145   ```
146
1474. 在[module.json5配置文件](../quick-start/module-configuration-file.md)中注册WorkSchedulerExtensionAbility,并设置如下标签:
148
149   - type标签设置为“workScheduler”。
150
151   - srcEntry标签设置为当前ExtensionAbility组件所对应的代码路径。
152
153   ```json
154   {
155     "module": {
156         "extensionAbilities": [
157           {
158             "name": "MyWorkSchedulerExtensionAbility",
159             "srcEntry": "./ets/WorkSchedulerExtension/WorkSchedulerExtension.ets",
160             "type": "workScheduler"
161           }
162         ]
163     }
164   }
165   ```
166
167
168### 实现延迟任务调度
169
1701. 导入模块。
171
172   ```ts
173   import { workScheduler } from '@kit.BackgroundTasksKit';
174   import { BusinessError } from '@kit.BasicServicesKit';
175   ```
176
1772. 申请延迟任务。
178
179   ```ts
180   // 创建workinfo
181   const workInfo: workScheduler.WorkInfo = {
182     workId: 1,
183     networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
184     bundleName: 'com.example.application',
185     abilityName: 'MyWorkSchedulerExtensionAbility'
186   }
187
188   try {
189     workScheduler.startWork(workInfo);
190     console.info(`startWork success`);
191   } catch (error) {
192     console.error(`startWork failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
193   }
194   ```
195
1963. 取消延迟任务。
197
198   ```ts
199   // 创建workinfo
200   const workInfo: workScheduler.WorkInfo = {
201     workId: 1,
202     networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
203     bundleName: 'com.example.application',
204     abilityName: 'MyWorkSchedulerExtensionAbility'
205   }
206
207   try {
208     workScheduler.stopWork(workInfo);
209     console.info(`stopWork success`);
210   } catch (error) {
211     console.error(`stopWork failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
212   }
213   ```
214
215## 相关实例
216
217针对延迟任务调度的开发,有以下相关示例可供参考:
218
219- [延迟任务调度(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/SystemFeature/TaskManagement/WorkScheduler)