一、概述

1.1 功能介紹

應用退至後台後,需要執行實時性要求不高的任務,例如有網絡時不定期主動獲取郵件等,可以使用延遲任務。當應用滿足設定的觸發條件(包括網絡類型、充電類型、存儲狀態、電池狀態、定時狀態等)時,將任務添加到執行隊列,系統會根據內存、功耗、設備温度、用户使用習慣等統一調度拉起應用。

1.2 運行原理
圖1 延遲任務實現原理

HarmonyOS:延遲任務(ArkTS)_鴻蒙

應用調用延遲任務接口添加、刪除、查詢延遲任務,延遲任務管理模塊會根據任務設置的條件(通過WorkInfo參數設置,包括網絡類型、充電類型、存儲狀態等)和系統狀態(包括內存、功耗、設備温度、用户使用習慣等)統一決策調度時機。
當滿足調度條件或調度結束時,系統會回調應用WorkSchedulerExtensionAbility中 onWorkStart() 或 onWorkStop() 的方法,同時會為應用單獨創建一個Extension擴展進程用以承載WorkSchedulerExtensionAbility,並給WorkSchedulerExtensionAbility一定的活動週期,開發者可以在對應回調方法中實現自己的任務邏輯。

1.3 約束與限制
  • 數量限制:一個應用同一時刻最多申請10個延遲任務。
  • 執行頻率限制:系統會根據應用的活躍分組,對延遲任務做分級管控,限制延遲任務調度的執行頻率。

表1 應用活躍程度分組

應用活躍分組

延遲任務執行頻率

活躍分組

最小間隔2小時

經常使用分組

最小間隔4小時

常用分組

最小間隔24小時

極少使用分組

最小間隔48小時

受限使用分組

禁止

從未使用分組

禁止

  • 超時:WorkSchedulerExtensionAbility單次回調最長運行2分鐘。如果超時不取消,系統會終止對應的Extension進程。
  • 調度延遲:系統會根據內存、功耗、設備温度、用户使用習慣等統一調度,如當系統內存資源不足或温度達到一定擋位時,系統將延遲調度該任務。
  • WorkSchedulerExtensionAbility接口調用限制:為實現對WorkSchedulerExtensionAbility能力的管控,在WorkSchedulerExtensionAbility中限制以下接口的調用: @ohos.resourceschedule.backgroundTaskManager (後台任務管理) @ohos.backgroundTaskManager (後台任務管理) @ohos.multimedia.camera (相機管理) @ohos.multimedia.audio (音頻管理) @ohos.multimedia.media (媒體服務)

二、接口説明

表2 延遲任務主要接口
以下是延遲任務開發使用的相關接口

接口名

接口描述

startWork(work: WorkInfo): void;

申請延遲任務

stopWork(work: WorkInfo, needCancel?: boolean): void;

取消延遲任務

getWorkStatus(workId: number, callback: AsyncCallback\): void;

獲取延遲任務狀態(Callback形式)

getWorkStatus(workId: number): Promise; 獲取延遲任務狀態(Promise形式)


obtainAllWorks(callback: AsyncCallback<Array\>): void;

獲取所有延遲任務(Callback形式)

obtainAllWorks(): Promise<Array\>;

獲取所有延遲任務(Promise形式)

stopAndClearWorks(): void;

停止並清除任務

isLastWorkTimeOut(workId: number, callback: AsyncCallback): void;

獲取上次任務是否超時(針對RepeatWork,Callback形式)

isLastWorkTimeOut(workId: number): Promise;

獲取上次任務是否超時(針對RepeatWork,Promise形式)

表3 WorkInfo參數

名稱

類型

只讀

可選

説明

workId

number



延遲任務ID。

bundleName

string



延遲任務所在應用的包名。

abilityName

string



包內ability名稱。

networkType

NetworkType



網絡類型。

isCharging

boolean



是否充電。

- true表示充電觸發延遲任務回調。

- false表示不充電觸發延遲任務回調。

chargerType

ChargingType



充電類型。

batteryLevel

number



電量。

batteryStatus

BatteryStatus



電池狀態。

storageRequest

StorageRequest



存儲狀態。

isRepeat

boolean



是否循環任務。

- true表示循環任務。

- false表示非循環任務。

repeatCycleTime

number



循環間隔,單位為毫秒。

repeatCount

number



循環次數。

isPersisted

boolean



註冊的延遲任務是否可保存在系統中。

- true表示可保存,即系統重啓後,任務可恢復。

- false表示不可保存。

isDeepIdle

boolean



是否要求設備進入空閒狀態。

- true表示需要。

- false表示不需要。

idleWaitTime

number



空閒等待時間,單位為毫秒。

parameters

\[key: string]: number | string | boolean



攜帶參數信息。

WorkInfo參數用於設置延遲任務的觸發條件,參數設置時需遵循以下規則:

  • workId、bundleName、abilityName為必填項,bundleName需為本應用包名。
  • 攜帶參數信息僅支持number、string、boolean三種類型。
  • 至少設置一個滿足的條件,包括網絡類型、充電類型、存儲狀態、電池狀態、定時狀態等。
  • 對於重複任務,任務執行間隔至少2小時。設置重複任務時間間隔時,須同時設置是否循環或循環次數中的一個。

表4 延遲任務回調接口
以下是延遲任務回調開發使用的相關接口,更多接口及使用方式請見延遲任務調度回調文檔。

接口名

接口描述

onWorkStart(work: workScheduler.WorkInfo): void

延遲調度任務開始的回調

onWorkStop(work: workScheduler.WorkInfo): void

延遲調度任務結束的回調

三、開發步驟

延遲任務調度開發步驟分為兩步:實現延遲任務調度擴展能力、實現延遲任務調度。

  1. 延遲任務調度擴展能力:實現WorkSchedulerExtensionAbility開始和結束的回調接口。
  2. 延遲任務調度:調用延遲任務接口,實現延遲任務申請、取消等功能。
3.1 實現延遲任務回調擴展能力
  1. 新建工程目錄。 在工程entry Module對應的ets目錄(./entry/src/main/ets)下,新建目錄及ArkTS文件,例如新建一個目錄並命名為WorkSchedulerExtension。在WorkSchedulerExtension目錄下,新建一個ArkTS文件並命名為WorkSchedulerExtension.ets,用以實現延遲任務回調接口。
  2. 導入模塊。
import { WorkSchedulerExtensionAbility, workScheduler } from '@kit.BackgroundTasksKit';
  1. 實現WorkSchedulerExtension生命週期接口。
export default class MyWorkSchedulerExtensionAbility extends WorkSchedulerExtensionAbility {
  // 延遲任務開始回調
  onWorkStart(workInfo: workScheduler.WorkInfo) {
    console.info(`onWorkStart, workInfo = ${JSON.stringify(workInfo)}`);
    // 打印 parameters中的參數,如:參數key1
    // console.info(`work info parameters: ${JSON.parse(workInfo.parameters?.toString()).key1}`)
  }

  // 延遲任務結束回調。當延遲任務2分鐘超時或應用調用stopWork接口取消任務時,觸發該回調。
  onWorkStop(workInfo: workScheduler.WorkInfo) {
    console.info(`onWorkStop, workInfo is ${JSON.stringify(workInfo)}`);
  }
}
  1. 在module.json5配置文件中註冊WorkSchedulerExtensionAbility,並設置如下標籤:
  • type標籤設置為“workScheduler”。
  • srcEntry標籤設置為當前ExtensionAbility組件所對應的代碼路徑。
{
  "module": {
      "extensionAbilities": [
        {
          "name": "MyWorkSchedulerExtensionAbility",
          "srcEntry": "./ets/WorkSchedulerExtension/WorkSchedulerExtension.ets",
          "type": "workScheduler"
        }
      ]
  }
}
3.2 實現延遲任務調度
示例效果圖

HarmonyOS:延遲任務(ArkTS)_鴻蒙_02

示例完整代碼WorkSchedulerExtension.ets

import { workScheduler, WorkSchedulerExtensionAbility } from '@kit.BackgroundTasksKit';
import { BusinessError } from '@kit.BasicServicesKit';

const TAG = "MyWorkSchedulerExtensionAbility"
export default class MyWorkSchedulerExtensionAbility extends WorkSchedulerExtensionAbility {
  // 延遲任務開始回調
  onWorkStart(workInfo: workScheduler.WorkInfo) {
    console.info(`${TAG} onWorkStart 回調, workInfo = ${JSON.stringify(workInfo)}`);
    // 打印 parameters中的參數,如:參數key1
    // console.info(`work info parameters: ${JSON.parse(workInfo.parameters?.toString()).key1}`)
  }
  // 延遲任務結束回調。當延遲任務2分鐘超時或應用調用stopWork接口取消任務時,觸發該回調。
  onWorkStop(workInfo: workScheduler.WorkInfo) {
    console.info(`${TAG} onWorkStop 回調, workInfo is ${JSON.stringify(workInfo)}`);
  }

  /**
   * 申請延遲任務。
   */
  startWorkScheduler() {
    // 創建workinfo
    const workInfo: workScheduler.WorkInfo = {
      workId: 1,
      networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
      bundleName: 'com.learn.learnharmonyos',
      abilityName: 'MyWorkSchedulerExtensionAbility'
    }

    try {
      workScheduler.startWork(workInfo);
      console.info(`${TAG} 執行 startWorkScheduler startWork success`);
    } catch (error) {
      console.error(`TAG} 執行 startWorkScheduler startWork failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
    }
  }

  /**
   * 取消延遲任務。
   */
  stopWorkScheduler() {
    // 創建workinfo
    const workInfo: workScheduler.WorkInfo = {
      workId: 1,
      networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
      bundleName: 'com.example.application',
      abilityName: 'MyWorkSchedulerExtensionAbility'
    }

    try {
      workScheduler.stopWork(workInfo);
      console.info(`stopWork success`);
    } catch (error) {
      console.error(`stopWork failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
    }
  }
}

TestBackgroundTasksKit4.ets

import MyWorkSchedulerExtensionAbility from '../../workSchedulerExtension/WorkSchedulerExtension'
@Entry
@Component
struct TestBackgroundTasksKit4 {
  myWorkSchedulerExtensionAbility: MyWorkSchedulerExtensionAbility = new MyWorkSchedulerExtensionAbility()

  build() {
    Column({space: 20}) {
      Button('申請延遲任務')
        .fontColor(Color.Black)
        .fontSize(20)
        .margin({top: 10})
        .onClick(() => {
          this.myWorkSchedulerExtensionAbility.startWorkScheduler()
        })
      Button('取消延遲任務')
        .fontColor(Color.Black)
        .margin({top: 10})
        .fontSize(20)
        .onClick(() => {
          this.myWorkSchedulerExtensionAbility.stopWorkScheduler()
        })
    }
    .height('100%')
    .width('100%')
  }
}
3.3 延遲任務調度功能驗證

確認延遲任務WorkSchedulerExtensionAbility回調方法onWorkStart、onWorkStop實現是否正確、是否可以成功回調
延遲任務申請成功之後,需要等到條件滿足後才可以執行延遲任務回調,為了快速驗證延遲任務回調功能是否正確,可以通過以下hidumper命令手動觸發延遲任務執行回調。

$ hidumper -s 1904 -a '-t com.example.application MyWorkSchedulerExtensionAbility'

-------------------------------[ability]-------------------------------


----------------------------------WorkSchedule----------------------------------

提醒 需要先配置hidumper系統環境變量