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