Deferred Task

Overview

Introduction

If an application needs to execute a non-real-time task after switching to the background, for example, if the application wants to obtain emails irregularly when the network is available, the application can request deferred tasks. When the specified conditions (including the network type, charging type, storage status, battery status, and timing status) are met, the system adds the task to the execution queue. Then the system starts the application to execute the task based on the memory, power consumption, device temperature, and user habits.

Working Principle

Figure 1 Working principle of deferred task scheduling

WorkScheduler

An application calls the WorkScheduler APIs to add, delete, and query deferred tasks. Based on the task-specific conditions (specified by WorkInfo, including the network type, charging type, and storage status) and system status (including the memory, power consumption, device temperature, and user habits), the WorkSchedulerService determines the time to schedule the tasks.

When the scheduling conditions are met or the task scheduling ends, the system calls back onWorkStart() or onWorkStop() in WorkSchedulerExtensionAbility. The system also creates an independent process for the WorkSchedulerExtensionAbility and provides a duration for the WorkSchedulerExtensionAbility to run. You can implement your own service logic in the callback functions.

Constraints

  • Quantity limit: An application can request a maximum of 10 deferred tasks during a time segment.

  • Execution frequency limit: The system controls the execution frequency of deferred tasks based on the application activity group. Applications that request the WORK_SCHEDULER resource are placed in the efficiency resource exemption group.

    Table 1 Application activity groups

Group Deferred Task Execution Frequency
Group of active applications At a minimum interval of 2 hours
Group of frequently used applications At a minimum interval of 4 hours
Group of applications that are used neither frequently nor rarely At a minimum interval of 24 hours
Group of rarely used applications At a minimum interval of 48 hours
Group of restricted applications Forbidden
Group of applications never used Forbidden
Efficiency resource exemption group No restriction

Available APIs

The table below lists the APIs used for developing deferred tasks. For details about more APIs and their usage, see @ohos.resourceschedule.workScheduler (Deferred Task Scheduling).

Table 2 Main APIs for deferred tasks

API Description
startWork(work: WorkInfo): void; Starts a deferred task.
stopWork(work: WorkInfo, needCancel?: boolean): void; Stops a deferred task.
getWorkStatus(workId: number, callback: AsyncCallback<WorkInfo>): void; Obtains the information about a deferred task. This API uses an asynchronous callback to return the result.
getWorkStatus(workId: number): Promise<WorkInfo>; Obtains the information about a deferred task. This API uses a promise to return the result.
obtainAllWorks(callback: AsyncCallback<Array<WorkInfo>>): void; Obtains all the deferred tasks. This API uses an asynchronous callback to return the result.
obtainAllWorks(): Promise<Array<WorkInfo>>; Obtains all the deferred tasks. This API uses a promise to return the result.
stopAndClearWorks(): void; Stops and clears all the deferred tasks.
isLastWorkTimeOut(workId: number, callback: AsyncCallback<boolean>): void; Checks whether the last execution of a deferred task has timed out. This API uses an asynchronous callback to return the result. It is applicable to repeated tasks.
isLastWorkTimeOut(workId: number): Promise<boolean>; Checks whether the last execution of a deferred task has timed out. This API uses a promise to return the result. It is applicable to repeated tasks.

Table 3 Options of WorkInfo

Name Type Mandatory Description
workId number Yes ID of a deferred task.
bundleName string Yes Bundle name of the application that requests the deferred task.
abilityName string Yes Name of the ability to be notified by a deferred task scheduling callback.
networkType NetworkType No Network type.
isCharging boolean No Whether the device needs to enter the charging state to trigger deferred task scheduling.
The value true means that the device needs to enter the charging state to trigger deferred task scheduling, and false means the opposite.
chargerType ChargingType No Charging type.
batteryLevel number No Battery level.
batteryStatus BatteryStatus No Battery status.
storageRequest StorageRequest No Storage status.
isRepeat boolean No Whether the deferred task is repeated.
The value** true** means that the task is repeated, and false means the opposite.
repeatCycleTime number No Repeat interval, in milliseconds.
repeatCount number No Number of repeat times.
isPersisted boolean No Whether to enable persistent storage for the deferred task.
The value true means to enable persistent storage for the task, and false means the opposite.
isDeepIdle boolean No Whether the device needs to enter the idle state to trigger deferred task scheduling.
The value true means that the device needs to enter the idle state to trigger deferred task scheduling, and false means the opposite.
idleWaitTime number No Time to wait in the idle state before triggering deferred task scheduling, in milliseconds.
parameters [key: string]: number | string | boolean No Carried parameters.

The WorkInfo parameter is used to set conditions for triggering task scheduling. Its setting must comply with the following rules:

  • workId, bundleName, and abilityName are mandatory. bundleName must be set to the bundle name of the current application.

  • The carried parameters can be of the number, string, or boolean type.

  • At least one condition must be set, including the network type, charging type, storage status, battery status, and timing status.

  • For repeated tasks, repeatCycleTime must be at least 20 minutes. When isRepeat is set, you must set repeatCycleTime or repeatCount.

The table below lists the APIs used for developing deferred task scheduling callbacks. For details about more APIs and their usage, see @ohos.WorkSchedulerExtensionAbility (Deferred Task Scheduling Callbacks).

Table 4 Deferred task scheduling callbacks

API Description
onWorkStart(work: workScheduler.WorkInfo): void Called when the system starts scheduling the deferred task.
onWorkStop(work: workScheduler.WorkInfo): void Called when the system stops scheduling the deferred task.

How to Develop

The development of deferred task scheduling consists of two steps: implementing the deferred task scheduling capability and implementing deferred task scheduling.

  1. Implementing the deferred task scheduling capability: Implement the callbacks for starting and stopping the WorkSchedulerExtensionAbility.

  2. Implementing deferred task scheduling: Call the WorkScheduler APIs to start and stop delayed tasks.

Implementing Deferred Task Scheduling Callbacks

  1. Create a project directory.

    In the ./entry/src/main/ets directory of the project, create a directory and an ArkTS file. For example, create a directory and name it WorkSchedulerExtension. In the WorkSchedulerExtension directory, create an ArkTS file named WorkSchedulerExtension.ets and implement the callbacks for deferred task scheduling.

  2. Import the module.

    import WorkSchedulerExtensionAbility from '@ohos.WorkSchedulerExtensionAbility';
    import workScheduler from '@ohos.resourceschedule.workScheduler';
    
  3. Implement the lifecycle callbacks for the WorkSchedulerExtensionAbility.

    export default class MyWorkSchedulerExtensionAbility extends WorkSchedulerExtensionAbility {
      // Callback invoked when the system starts scheduling the deferred task.
      onWorkStart(workInfo: workScheduler.WorkInfo) {
        console.info(`onWorkStart, workInfo = ${JSON.stringify(workInfo)}`);
      }
    
      // Callback invoked when the system stops scheduling the deferred task.
      onWorkStop(workInfo: workScheduler.WorkInfo) {
        console.info(`onWorkStop, workInfo is ${JSON.stringify(workInfo)}`);
      }
    }
    
  4. Register the WorkSchedulerExtensionAbility in the module.json5 file and set the tags as follows:

    • Set type to workScheduler.

    • Set srcEntry to the code path of the WorkSchedulerExtensionAbility component.

    {
      "module": {
          "extensionAbilities": [
            {
              "name": "MyWorkSchedulerExtensionAbility",
              "srcEntry": "./ets/WorkSchedulerExtension/WorkSchedulerExtension.ets",
              "label": "$string:WorkSchedulerExtensionAbility_label",
              "description": "$string:WorkSchedulerExtensionAbility_desc",
              "type": "workScheduler"
            }
          ]
      }
    }
    

Implementing Deferred Task Scheduling

  1. Import the module.

    import workScheduler from '@ohos.resourceschedule.workScheduler';
    import { BusinessError } from '@ohos.base';
    
  2. Start a deferred task.

    const workInfo: workScheduler.WorkInfo = {
      workId: 1,
      networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
      bundleName: 'com.example.application',
      abilityName: 'MyWorkSchedulerExtensionAbility'
    }
    
    try {
      workScheduler.startWork(workInfo);
      console.info(`startWork success`);
    } catch (error) {
      console.error(`startWork failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
    }
    
  3. Cancel the deferred task.

    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}`);
    }
    

More About Debugging

During debugging in DevEco Studio, the WorkSchedulerExeAbility can submit a task by calling startWork. The system checks whether the last task provided by the application has been finished and executes the new task only when it has been finished. If you want the system to execute the new task without waiting, call stopWork or stopAndClearWorks before submitting the new task.