• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Continuous Task (ArkTS)
2
3<!--Kit: Background Tasks Kit-->
4<!--Subsystem: ResourceSchedule-->
5<!--Owner: @cheng-shichang-->
6<!--Designer: @zhouben25-->
7<!--Tester: @fenglili18-->
8<!--Adviser: @Brilliantry_Rui-->
9
10## Overview
11
12### Introduction
13
14If an application has a perceivable task that needs to run in an extended period of time in the background, it can request a continuous task to prevent itself from being suspended. Examples of continuous tasks include music playback and navigation in the background. Within a continuous task, the application can concurrently request multiple types of tasks and update the task types. When the application operates in the background, the system performs consistency check to ensure that the application is executing the corresponding continuous task. Upon successful request for a continuous task, the notification panel displays the message associated with the task. If the user deletes the message, the system automatically terminates the task.
15
16### Use Cases
17
18The table below lists the types of continuous tasks, which are used in various scenarios. You can select a task type suitable for your case based on the description.
19
20**Table 1** Continuous task types
21| Name| Description| Item| Example Scenario|
22| -------- | -------- | -------- | -------- |
23| DATA_TRANSFER | Data transfer| dataTransfer | Non-hosting uploading and downloading operations, like those occurring in the background of a web browser for data transfer.|
24| AUDIO_PLAYBACK | Audio and video playback| audioPlayback | Audio and video playback in the background; audio and video casting.<br> **Note**: It can be used in atomic services.|
25| AUDIO_RECORDING | Audio recording| audioRecording | Recording and screen capture in the background.|
26| LOCATION | Positioning and navigation| location | Positioning and navigation.|
27| BLUETOOTH_INTERACTION | Bluetooth-related services| bluetoothInteraction | An application transitions into the background during the process of file transfer using Bluetooth.|
28| MULTI_DEVICE_CONNECTION | Multi-device connection| multiDeviceConnection | Distributed service connection and casting.<br> **Note**: It can be used in atomic services.|
29| <!--DelRow-->WIFI_INTERACTION | WLAN-related services (for system applications only)| wifiInteraction  | An application transitions into the background during the process of file transfer using WLAN.|
30| VOIP<sup>13+</sup> | Audio and video calls| voip  | Chat applications (with audio and video services) transition into the background during audio and video calls.|
31| TASK_KEEPING | Computing task (for 2-in-1 devices only).| taskKeeping  | Antivirus software is running.|
32
33Description of **DATA_TRANSFER**:
34
35- During data transfer, if an application uses the [upload and download agent API](../reference/apis-basic-services-kit/js-apis-request.md) to hand over tasks to the system, the application will be suspended in the background even if it has requested the continuous task of the DATA_TRANSFER type.
36
37- During data transfer, the application needs to update the progress. If the progress is not updated for more than 10 minutes, the continuous task of the DATA_TRANSFER type will be canceled. For details about how to update the progress, see the example in [startBackgroundRunning()](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-backgroundTaskManager.md#backgroundtaskmanagerstartbackgroundrunning12).
38
39Description of **AUDIO_PLAYBACK**:
40
41- Casting audio and video involves transmitting content from one device to another for playback purposes. If the application transitions to the background while casting, the continuous task checks the audio and video playback and casting services. The task will persist as long as either the audio and video playback or casting service is running properly.
42
43- If the application needs to play media (STREAM_USAGE_MUSIC, STREAM_USAGE_MOVIE, or STREAM_USAGE_AUDIOBOOK) or games (STREAM_USAGE_GAME) in the background, it must access the [AVSession](../media/avsession/avsession-overview.md) service and request a continuous task of the AUDIO_PLAYBACK type.
44
45- If the application is required to run other background playback tasks that can be perceived by users for a long time, it must request a continuous task of the AUDIO_PLAYBACK type, without accessing the AVSession service.
46
47- If the application does not comply with the preceding access specifications, it will be muted and suspended by the system when switched to the background. It can resume playback only when it returns to the foreground.
48
49### Constraints
50
51**Ability restrictions**: In the stage model, only the UIAbility can request continuous tasks. In the FA model, only the ServiceAbility can request continuous tasks. Continuous tasks can be requested by the current application on the current device or across devices or by other applications. However, the capability to make cross-device or cross-application requests is restricted to system applications.
52
53**Quantity restrictions**: A UIAbility (ServiceAbility in the FA model) can request only one continuous task at a time. If a UIAbility has a running continuous task, it can request another one only after the running task is finished. If an application needs to request multiple continuous tasks at the same time, it must create multiple UIAbilities. After a UIAbility requests a continuous task, all the processes of the application are not suspended.
54
55**Running restrictions**:
56
57- If an application requests a continuous task but does not carry out the relevant service, the system imposes restrictions on the application. For example, if the system detects that an application has requested a continuous task of the AUDIO_PLAYBACK type but does not play audio, the application will be suspended when it returns to the background.
58
59- If an application requests a continuous task but carries out a service that does not match the requested type, the system imposes restrictions on the application. The application will be suspended when it returns to the background. For example, if the system detects that an application requests a continuous task of the AUDIO_PLAYBACK type, but the application is playing audio (corresponding to the AUDIO_PLAYBACK type) and recording (corresponding to the AUDIO_RECORDING type), the system enforces management measures.
60
61- When an application's operations are completed after a continuous task request, the system imposes restrictions on the application. The application will be suspended when it returns to the background.
62
63- If the background load of the process that runs a continuous task is higher than the corresponding typical load for a long period of time, the system performs certain control. The application will be suspended or terminated when it is switched to the background.
64
65> **NOTE**
66>
67> The application shall proactively cancel a continuous task when it is finished. Otherwise, the system will forcibly cancel the task. For example, when a user taps the UI to pause music playback, the application must cancel the continuous task in a timely manner. When the user taps the UI again to continue music playback, the application needs to request a continuous task.
68>
69> If an application that plays an audio in the background is [interrupted](../media/audio/audio-playback-concurrency.md), the system automatically detects and stops the continuous task. The application must request a continuous task again to restart the playback.
70>
71> When an application that plays audio in the background stops a continuous task, it must suspend or stop the audio stream. Otherwise, the application will be forcibly terminated by the system.
72
73## Available APIs
74
75**Table 2** Main APIs for continuous tasks
76
77The table below uses promise as an example to describe the APIs used for developing continuous tasks. For details about more APIs and their usage, see [Background Task Management](../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-backgroundTaskManager.md).
78
79| API| Description|
80| -------- | -------- |
81| startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: [WantAgent](../reference/apis-ability-kit/js-apis-app-ability-wantAgent.md)): Promise&lt;void&gt; | Requests a continuous task.|
82| stopBackgroundRunning(context: Context): Promise&lt;void&gt; | Cancels a continuous task.|
83
84## How to Develop
85
86The following walks you through how to request a continuous task for recording to implement the following functions:
87
88- When a user touches **Request Continuous Task**, the application requests a continuous task for recording, and a message is displayed in the notification bar, indicating that a recording task is running.
89
90- When a user touches **Cancel Continuous Task**, the application cancels the continuous task, and the notification message is removed.
91
92### Stage Model
93
941. Declare the **ohos.permission.KEEP_BACKGROUND_RUNNING** permission. For details, see [Declaring Permissions](../security/AccessToken/declare-permissions.md).
95
962. Declare the continuous task type.
97   Declare the type of the continuous task for the target UIAbility in the **module.json5** file. Set the corresponding [configuration item](continuous-task.md#use-cases) in the configuration file.
98
99   ```json
100    "module": {
101        "abilities": [
102            {
103                "backgroundModes": [
104                 // Configuration item of the continuous task type
105                "audioRecording"
106                ]
107            }
108        ],
109        // ...
110    }
111   ```
112
1133. Import the modules.
114
115   Import the modules related to continuous tasks: @ohos.resourceschedule.backgroundTaskManager and @ohos.app.ability.wantAgent. Import other modules based on the project requirements.
116
117   <!--RP1-->
118   ```ts
119    import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
120    import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
121    import { window } from '@kit.ArkUI';
122    import { rpc } from '@kit.IPCKit'
123    import { BusinessError } from '@kit.BasicServicesKit';
124    import { wantAgent, WantAgent } from '@kit.AbilityKit';
125    // In atomic services, please remove the WantAgent import.
126   ```
127   <!--RP1End-->
128
1294. Request and cancel a continuous task.
130
131   The code snippet below shows how an application requests a continuous task for itself.
132
133   ```ts
134    function callback(info: backgroundTaskManager.ContinuousTaskCancelInfo) {
135      // ID of a continuous task.
136      console.info('OnContinuousTaskCancel callback id ' + info.id);
137      // Reason for canceling the continuous task.
138      console.info('OnContinuousTaskCancel callback reason ' + info.reason);
139    }
140
141    @Entry
142    @Component
143    struct Index {
144      @State message: string = 'ContinuousTask';
145     // Obtain the UIAbility context of the page by calling getUIContext().getHostContext().
146      private context: Context | undefined = this.getUIContext().getHostContext();
147
148      OnContinuousTaskCancel() {
149        try {
150           backgroundTaskManager.on("continuousTaskCancel", callback);
151           console.info(`Succeeded in operationing OnContinuousTaskCancel.`);
152        } catch (error) {
153           console.error(`Operation OnContinuousTaskCancel failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
154        }
155      }
156
157      OffContinuousTaskCancel() {
158        try {
159           // If the callback parameter is not passed, all callbacks associated with the specified event are canceled.
160           backgroundTaskManager.off("continuousTaskCancel", callback);
161           console.info(`Succeeded in operationing OffContinuousTaskCancel.`);
162        } catch (error) {
163           console.error(`Operation OffContinuousTaskCancel failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
164        }
165      }
166
167      // Request a continuous task using .then().
168      startContinuousTask() {
169        let wantAgentInfo: wantAgent.WantAgentInfo = {
170          // List of operations to be executed after the notification is clicked.
171          // Add the bundleName and abilityName of the application to start.
172          wants: [
173            {
174              bundleName: "com.example.myapplication",
175              abilityName: "MainAbility"
176            }
177          ],
178          // Specify the action to perform (starting the ability) after the notification message is clicked.
179          actionType: wantAgent.OperationType.START_ABILITY,
180          // Custom request code.
181          requestCode: 0,
182          // Execution attribute of the operation to perform after the notification is clicked.
183          actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG],
184          // CAR_KEY subtype, which takes effect only when a continuous task of the bluetoothInteraction type is requested.
185          // Ensure that the key value in the extraInfo parameter is backgroundTaskManager.BackgroundModeType.SUB_MODE. Otherwise, the subtype does not take effect.
186          // extraInfo: { [backgroundTaskManager.BackgroundModeType.SUB_MODE] : backgroundTaskManager.BackgroundSubMode.CAR_KEY }
187        };
188
189        try {
190          // Obtain the WantAgent object by using the getWantAgent API of the wantAgent module.
191          // In atomic services, replace the following line of code with wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: object) => {.
192          wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
193            try {
194              let list: Array<string> = ["audioRecording"];
195              // let list: Array<string> = ["bluetoothInteraction"]; The bluetoothInteraction type is included in the continuous task, and the CAR_KEY subtype is valid.
196              // In atomic services, let list: Array<string> = ["audioPlayback"];
197              backgroundTaskManager.startBackgroundRunning(this.context, list, wantAgentObj).then((res: backgroundTaskManager.ContinuousTaskNotification) => {
198                console.info("Operation startBackgroundRunning succeeded");
199                // Execute the continuous task logic, for example, recording.
200              }).catch((error: BusinessError) => {
201                console.error(`Failed to Operation startBackgroundRunning. code is ${error.code} message is ${error.message}`);
202              });
203            } catch (error) {
204              console.error(`Failed to Operation startBackgroundRunning. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
205            }
206          });
207        } catch (error) {
208          console.error(`Failed to Operation getWantAgent. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
209        }
210      }
211
212      // Request a continuous task using async/await.
213      // async startContinuousTask() {
214      //   let wantAgentInfo: wantAgent.WantAgentInfo = {
215      //     // List of operations to be executed after the notification is touched.
216      //     // Add the bundleName and abilityName of the application to start.
217      //     wants: [
218      //       {
219      //         bundleName: "com.example.myapplication",
220      //         abilityName: "MainAbility"
221      //       }
222      //     ],
223      //     // Specify the action to perform (starting the ability) after the notification message is clicked.
224      //     actionType: wantAgent.OperationType.START_ABILITY,
225      //     // Custom request code.
226      //     requestCode: 0,
227      //     // Execution attribute of the operation to perform after the notification is clicked.
228      //     actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG],
229      //     // CAR_KEY subtype, which takes effect only when a continuous task of the bluetoothInteraction type is requested.
230      //     // Ensure that the key value in the extraInfo parameter is backgroundTaskManager.BackgroundModeType.SUB_MODE. Otherwise, the subtype does not take effect.
231      //     // extraInfo: { [backgroundTaskManager.BackgroundModeType.SUB_MODE] : backgroundTaskManager.BackgroundSubMode.CAR_KEY }
232      //   };
233      //
234      //   try {
235      //     // Obtain the WantAgent object by using the getWantAgent API of the wantAgent module.
236      //     // In atomic services, replace the following line of code with const wantAgentObj: object = await wantAgent.getWantAgent(wantAgentInfo);.
237      //     const wantAgentObj: WantAgent = await wantAgent.getWantAgent(wantAgentInfo);
238      //     try {
239      //       let list: Array<string> = ["audioRecording"];
240      //       // let list: Array<string> = ["bluetoothInteraction"]; The bluetoothInteraction type is included in the continuous task, and the CAR_KEY subtype is valid.
241      //       // In atomic services, let list: Array<string> = ["audioPlayback"];
242      //       const res: backgroundTaskManager.ContinuousTaskNotification = await backgroundTaskManager.startBackgroundRunning(this.context as Context, list, wantAgentObj);
243      //       console.info(`Operation startBackgroundRunning succeeded, notificationId: ${res.notificationId}`);
244      //       // Execute the continuous task logic, for example, recording.
245      //     } catch (error) {
246      //       console.error(`Failed to Operation startBackgroundRunning. Code is ${(error as BusinessError).code}, message is ${(error as BusinessError).message}`);
247      //     }
248      //   } catch (error) {
249      //     console.error(`Failed to Operation getWantAgent. Code is ${(error as BusinessError).code}, message is ${(error as BusinessError).message}`);
250      //   }
251      // }
252
253      // Cancel a continuous task using .then().
254      stopContinuousTask() {
255         backgroundTaskManager.stopBackgroundRunning(this.context).then(() => {
256           console.info(`Succeeded in operationing stopBackgroundRunning.`);
257         }).catch((err: BusinessError) => {
258           console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
259         });
260      }
261
262      // Cancel a continuous task using async/await.
263      // async stopContinuousTask() {
264      //   try {
265      //     await backgroundTaskManager.stopBackgroundRunning(this.context);
266      //     console.info(`Succeeded in operationing stopBackgroundRunning.`);
267      //   } catch (error) {
268      //     console.error(`Failed to operation stopBackgroundRunning. Code is ${(error as BusinessError).code}, message is ${(error as BusinessError).message}`)
269      //   }
270      // }
271
272      build() {
273        Row() {
274          Column() {
275            Text("Index")
276              .fontSize(50)
277              .fontWeight(FontWeight.Bold)
278
279           Button() {
280              Text('Request continuous task').fontSize(25).fontWeight(FontWeight.Bold)
281            }
282            .type(ButtonType.Capsule)
283            .margin({ top: 10 })
284            .backgroundColor('#0D9FFB')
285            .width(250)
286            .height(40)
287            .onClick(() => {
288              // Request a continuous task by clicking a button.
289              this.startContinuousTask();
290            })
291
292            Button() {
293              Text('Cancel continuous task').fontSize (25).fontWeight (FontWeight.Bold)
294            }
295            .type(ButtonType.Capsule)
296            .margin({ top: 10 })
297            .backgroundColor('#0D9FFB')
298            .width(250)
299            .height(40)
300            .onClick(() => {
301              // Stop the continuous task.
302
303              // Cancel the continuous task by clicking a button.
304              this.stopContinuousTask();
305            })
306
307            Button() {
308              Text('Register a callback for canceling a continuous task').fontSize (25).fontWeight(FontWeight.Bold)
309            }
310            .type(ButtonType.Capsule)
311            .margin({ top: 10 })
312            .backgroundColor('#0D9FFB')
313            .width(250)
314            .height(40)
315            .onClick(() => {
316              // Use a button to register a callback for canceling a continuous task.
317              this.OnContinuousTaskCancel();
318            })
319
320            Button() {
321              Text('Unregister a callback for canceling a continuous task').fontSize (25).fontWeight(FontWeight.Bold)
322            }
323            .type(ButtonType.Capsule)
324            .margin({ top: 10 })
325            .backgroundColor('#0D9FFB')
326            .width(250)
327            .height(40)
328            .onClick(() => {
329              // Use a button to unregister a callback for canceling a continuous task.
330              this.OffContinuousTaskCancel();
331            })
332          }
333          .width('100%')
334        }
335        .height('100%')
336      }
337    }
338   ```
339   <!--Del-->
340
341   The code snippet below shows how an application requests a continuous task across devices or applications. When a continuous task is executed across devices or applications in the background, the UIAbility can be created and run in the background in call mode. For details, see [Using Call to Implement UIAbility Interaction (for System Applications Only)](../application-models/uiability-intra-device-interaction.md#using-call-to-implement-uiability-interaction-for-system-applications-only) and [Using Cross-Device Call](../application-models/hop-multi-device-collaboration.md#using-cross-device-call).
342
343   ```ts
344    const MSG_SEND_METHOD: string = 'CallSendMsg'
345
346    let mContext: Context;
347
348    function startContinuousTask() {
349      let wantAgentInfo : wantAgent.WantAgentInfo = {
350        // List of operations to be executed after the notification is clicked.
351        wants: [
352          {
353            bundleName: "com.example.myapplication",
354            abilityName: "com.example.myapplication.MainAbility",
355          }
356        ],
357        // Type of the operation to perform after the notification is clicked.
358        actionType: wantAgent.OperationType.START_ABILITY,
359        // Custom request code.
360        requestCode: 0,
361        // Execution attribute of the operation to perform after the notification is clicked.
362        actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
363      };
364
365      // Obtain the WantAgent object by using the getWantAgent API of the wantAgent module.
366      // In atomic services, replace the following line of code with wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: object) => {.
367      wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj : WantAgent) => {
368        backgroundTaskManager.startBackgroundRunning(mContext,
369          backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK, wantAgentObj).then(() => {
370          console.info(`Succeeded in operationing startBackgroundRunning.`);
371        }).catch((err: BusinessError) => {
372          console.error(`Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
373        });
374      });
375    }
376
377    function stopContinuousTask() {
378      backgroundTaskManager.stopBackgroundRunning(mContext).then(() => {
379        console.info(`Succeeded in operationing stopBackgroundRunning.`);
380      }).catch((err: BusinessError) => {
381        console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
382      });
383    }
384
385    class MyParcelable implements rpc.Parcelable {
386      num: number = 0;
387      str: string = '';
388
389      constructor(num: number, str: string) {
390        this.num = num;
391        this.str = str;
392      }
393
394      marshalling(messageSequence: rpc.MessageSequence) {
395        messageSequence.writeInt(this.num);
396        messageSequence.writeString(this.str);
397        return true;
398      }
399
400      unmarshalling(messageSequence: rpc.MessageSequence) {
401        this.num = messageSequence.readInt();
402        this.str = messageSequence.readString();
403        return true;
404      }
405    }
406
407    function sendMsgCallback(data: rpc.MessageSequence) {
408      console.info('BgTaskAbility funcCallBack is called ' + data);
409      let receivedData: MyParcelable = new MyParcelable(0, '');
410      data.readParcelable(receivedData);
411      console.info(`receiveData[${receivedData.num}, ${receivedData.str}]`);
412      // You can execute different methods based on the str value in the sequenceable data sent by the caller object.
413      if (receivedData.str === 'start_bgtask') {
414        // Request a continuous task.
415        startContinuousTask();
416      } else if (receivedData.str === 'stop_bgtask') {
417        // Cancel the continuous task.
418        stopContinuousTask();
419      }
420      return new MyParcelable(10, 'Callee test');
421    }
422
423    export default class BgTaskAbility extends UIAbility {
424      // Create an ability.
425      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
426        console.info("[Demo] BgTaskAbility onCreate");
427        try {
428          this.callee.on(MSG_SEND_METHOD, sendMsgCallback)
429        } catch (error) {
430          console.error(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`);
431        }
432        mContext = this.context;
433      }
434
435      // Destroy an ability.
436      onDestroy() {
437        console.info('[Demo] BgTaskAbility onDestroy');
438      }
439
440      onWindowStageCreate(windowStage: window.WindowStage) {
441        console.info('[Demo] BgTaskAbility onWindowStageCreate');
442
443        windowStage.loadContent('pages/Index', (error, data) => {
444          if (error.code) {
445            console.error(`load content failed with error ${JSON.stringify(error)}`);
446            return;
447          }
448          console.info(`load content succeed with data ${JSON.stringify(data)}`);
449        });
450      }
451
452      onWindowStageDestroy() {
453        console.info('[Demo] BgTaskAbility onWindowStageDestroy');
454      }
455
456      onForeground() {
457        console.info('[Demo] BgTaskAbility onForeground');
458      }
459
460      onBackground() {
461        console.info('[Demo] BgTaskAbility onBackground');
462      }
463    };
464   ```
465
466   <!--DelEnd-->
467
468<!--Del-->
469### FA Model
470
4711. Start and connect to a ServiceAbility.
472
473   - If no user interaction is required, use **startAbility()** to start the ServiceAbility. For details, see [ServiceAbility Component](../application-models/serviceability-overview.md). In the **onStart** callback of the ServiceAbility, call the APIs to request and cancel continuous tasks.
474
475   - If user interaction is required (for example, in music playback scenarios), use **connectAbility()** to start and connect to the ServiceAbility. For details, see [ServiceAbility Component](../application-models/serviceability-overview.md). After obtaining the agent of the ServiceAbility, the application can communicate with the ServiceAbility and control the request and cancellation of continuous tasks.
476
4772. Configure permissions and declare the continuous task type.
478
479   Declare the **ohos.permission.KEEP_BACKGROUND_RUNNING** permission in the **config.json** file. For details, see [Declaring Permissions](../security/AccessToken/declare-permissions.md). In addition, declare the continuous task type for the ServiceAbility.
480
481   ```json
482   "module": {
483       "package": "com.example.myapplication",
484       "abilities": [
485           {
486               "backgroundModes": [
487               "audioRecording"
488               ], // Background mode
489               "type": "service"  // The ability type is Service.
490           }
491       ],
492       "reqPermissions": [
493           {
494               "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" // Continuous task permission
495           }
496       ]
497   }
498   ```
499
5003. Import the modules.
501
502   ```js
503    import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
504    import { rpc } from '@kit.IPCKit'
505    import { BusinessError } from '@kit.BasicServicesKit';
506    import { wantAgent, WantAgent } from '@kit.AbilityKit';
507   ```
508
5094. Request and cancel a continuous task. In the ServiceAbility, call [startBackgroundRunning](#available-apis) and [stopBackgroundRunning](#available-apis) to request and cancel a continuous task. Use JavaScript code to implement this scenario.
510
511   ```js
512    function startContinuousTask() {
513      let wantAgentInfo: wantAgent.WantAgentInfo = {
514        // List of operations to be executed after the notification is clicked.
515        wants: [
516          {
517            bundleName: "com.example.myapplication",
518            abilityName: "com.example.myapplication.MainAbility"
519          }
520        ],
521        // Type of the operation to perform after the notification is clicked.
522        actionType: wantAgent.OperationType.START_ABILITY,
523        // Custom request code.
524        requestCode: 0,
525        // Execution attribute of the operation to perform after the notification is clicked.
526        actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
527      };
528
529      // Obtain the WantAgent object by using the getWantAgent API of the wantAgent module.
530      wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
531        backgroundTaskManager.startBackgroundRunning(featureAbility.getContext(),
532          backgroundTaskManager.BackgroundMode.AUDIO_RECORDING, wantAgentObj).then(() => {
533          console.info(`Succeeded in operationing startBackgroundRunning.`);
534        }).catch((err: BusinessError) => {
535          console.error(`Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
536        });
537      });
538    }
539
540    function stopContinuousTask() {
541      backgroundTaskManager.stopBackgroundRunning(featureAbility.getContext()).then(() => {
542        console.info(`Succeeded in operationing stopBackgroundRunning.`);
543      }).catch((err: BusinessError) => {
544        console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
545      });
546    }
547
548    async function processAsyncJobs() {
549      // Execute the continuous task.
550
551      // After the continuous task is complete, call the API to release resources.
552      stopContinuousTask();
553    }
554
555    let mMyStub: MyStub;
556
557    // Start the service by calling connectAbility().
558    class MyStub extends rpc.RemoteObject {
559      constructor(des: string) {
560        super(des);
561      }
562
563      onRemoteRequest(code: number, data: rpc.MessageParcel, reply: rpc.MessageParcel, option: rpc.MessageOption) {
564        console.log('ServiceAbility onRemoteRequest called');
565        // Custom request code.
566        if (code === 1) {
567          // Receive the request code for requesting a continuous task.
568          startContinuousTask();
569          // Execute the continuous task.
570        } else if (code === 2) {
571          // Receive the request code for canceling the continuous task.
572          stopContinuousTask();
573        } else {
574          console.log('ServiceAbility unknown request code');
575        }
576        return true;
577      }
578    }
579
580    // Start the service by calling startAbility().
581    class ServiceAbility {
582      onStart(want: Want) {
583        console.info('ServiceAbility onStart');
584        mMyStub = new MyStub("ServiceAbility-test");
585        // Call the API to start the task.
586        startContinuousTask();
587        processAsyncJobs();
588      }
589
590      onStop() {
591        console.info('ServiceAbility onStop');
592      }
593
594      onConnect(want: Want) {
595        console.info('ServiceAbility onConnect');
596        return mMyStub;
597      }
598
599      onReconnect(want: Want) {
600        console.info('ServiceAbility onReconnect');
601      }
602
603      onDisconnect() {
604        console.info('ServiceAbility onDisconnect');
605      }
606
607      onCommand(want: Want, startId: number) {
608        console.info('ServiceAbility onCommand');
609      }
610    }
611
612    export default new ServiceAbility();
613    ```
614<!--DelEnd-->
615
616