• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Continuous Task Development
2
3## When to Use
4
5If 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 so that it will not be suspended. Examples of continuous tasks include music playback, navigation, device connection, and VoIP.
6There is no time limit for a continuous task running in the background. To prevent abuse, the system limits the number of continuous tasks that can be requested. It also attaches a notification to each of the tasks so that the tasks are perceivable. In addition, the system verifies whether the application is actually executing a continuous task.
7
8## Available APIs
9
10**Table 1** Main APIs for continuous tasks
11
12| API                                     | Description                          |
13| ---------------------------------------- | ---------------------------- |
14| startBackgroundRunning(context: Context, bgMode: BackgroundMode, wantAgent: WantAgent): Promise<void> | Requests a continuous task from the system so that the application keeps running in the background.|
15| stopBackgroundRunning(context: Context): Promise<void> | Cancels the continuous task.                |
16
17
18For details about **wantAgent**, see [WantAgent](../reference/apis/js-apis-wantAgent.md).
19
20**Table 2** Background modes
21
22| Name                    | Description            | Item                  |
23| ----------------------- | -------------- | --------------------- |
24| DATA_TRANSFER           | Data transfer.          | dataTransfer          |
25| AUDIO_PLAYBACK          | Audio playback.          | audioPlayback         |
26| AUDIO_RECORDING         | Audio recording.            | audioRecording        |
27| LOCATION                | Positioning and navigation.          | location              |
28| BLUETOOTH_INTERACTION   | Bluetooth-related task.          | bluetoothInteraction  |
29| MULTI_DEVICE_CONNECTION | Multi-device connection.         | multiDeviceConnection |
30| WIFI_INTERACTION        | WLAN-related task (reserved).  | wifiInteraction       |
31| VOIP                    | Voice and video call (reserved).   | voip                  |
32| TASK_KEEPING            | Computing task (for specific devices only).| taskKeeping           |
33
34
35## How to Develop
36
37### Development in the FA Model
38
39For details about how to use the ServiceAbility in the FA model, see [ServiceAbility Component Overview](../application-models/serviceability-overview.md).
40
41If an application does not need to interact with a continuous task in the background, you can use **startAbility()** to start the ServiceAbility. In the **onStart** callback of the ServiceAbility, call **startBackgroundRunning()** to declare that the ServiceAbility needs to run in the background for a long time. After the task execution is complete, call **stopBackgroundRunning()** to release resources.
42
43If an application needs to interact with a continuous task in the background (for example, an application related to music playback), you can use **connectAbility()** to start and connect to the ServiceAbility. After obtaining the proxy of the ServiceAbility, the application can communicate with the ServiceAbility and control the request and cancellation of continuous tasks.
44
451. Configure the continuous task permission **ohos.permission.KEEP_BACKGROUND_RUNNING** in the **config.json** file, and declare the corresponding background mode type for the ServiceAbility that needs to use the task.
46
47   ```
48   "module": {
49       "package": "com.example.myapplication",
50       "abilities": [
51           {
52               "backgroundModes": [
53               "dataTransfer",
54               "location"
55               ], // Background mode
56               "type": "service"  // The ability type is Service.
57           }
58       ],
59       "reqPermissions": [
60           {
61               "name": "ohos.permission.KEEP_BACKGROUND_RUNNING"  // Continuous task permission
62           }
63       ]
64   }
65   ```
66
672. Call the APIs for requesting and canceling a continuous task in the ServiceAbility.
68
69   ```js
70   import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
71   import featureAbility from '@ohos.ability.featureAbility';
72   import wantAgent from '@ohos.wantAgent';
73   import rpc from "@ohos.rpc";
74
75   function startContinuousTask() {
76       let wantAgentInfo = {
77           // List of operations to be executed after the notification is clicked.
78           wants: [
79               {
80                   bundleName: "com.example.myapplication",
81                   abilityName: "com.example.myapplication.MainAbility"
82               }
83           ],
84           // Type of the operation to perform after the notification is clicked.
85           operationType: wantAgent.OperationType.START_ABILITY,
86           // Custom request code.
87           requestCode: 0,
88           // Execution attribute of the operation to perform after the notification is clicked.
89           wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
90       };
91
92       // Obtain the WantAgent object by using the getWantAgent API of the wantAgent module.
93       wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
94           try {
95               backgroundTaskManager.startBackgroundRunning(featureAbility.getContext(),
96                   backgroundTaskManager.BackgroundMode.DATA_TRANSFER, wantAgentObj).then(() => {
97                   console.info("Operation startBackgroundRunning succeeded");
98               }).catch((err) => {
99                   console.error("Operation startBackgroundRunning failed Cause: " + err);
100               });
101           } catch (error) {
102               console.error(`Operation startBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
103           }
104       });
105   }
106
107   function stopContinuousTask() {
108       try {
109           backgroundTaskManager.stopBackgroundRunning(featureAbility.getContext()).then(() => {
110               console.info("Operation stopBackgroundRunning succeeded");
111           }).catch((err) => {
112               console.error("Operation stopBackgroundRunning failed Cause: " + err);
113           });
114       } catch (error) {
115           console.error(`Operation stopBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
116       }
117   }
118
119   async function processAsyncJobs() {
120       // Execute the continuous task.
121
122       // After the continuous task is complete, call the API to release resources.
123       stopContinuousTask();
124   }
125
126   let mMyStub;
127
128   class MyStub extends rpc.RemoteObject {
129       constructor(des) {
130           if (typeof des === 'string') {
131               super(des);
132           } else {
133               return null;
134           }
135       }
136       onRemoteRequest(code, data, reply, option) {
137           console.log('ServiceAbility onRemoteRequest called');
138           // The meaning of code is user-defined.
139           if (code === 1) {
140               // Receive the request code for requesting a continuous task.
141               startContinuousTask();
142               // Execute the continuous task.
143           } else if (code === 2) {
144               // Receive the request code for canceling the continuous task.
145               stopContinuousTask();
146           } else {
147               console.log('ServiceAbility unknown request code');
148           }
149           return true;
150       }
151   }
152
153   export default {
154       onStart(want) {
155           console.info('ServiceAbility onStart');
156           mMyStub = new MyStub("ServiceAbility-test");
157           // Call the API to start the task.
158           startContinuousTask();
159           processAsyncJobs();
160       },
161       onStop() {
162           console.info('ServiceAbility onStop');
163       },
164       onConnect(want) {
165           console.info('ServiceAbility onConnect');
166           return mMyStub;
167       },
168       onReconnect(want) {
169           console.info('ServiceAbility onReconnect');
170       },
171       onDisconnect() {
172           console.info('ServiceAbility onDisconnect');
173       },
174       onCommand(want, restart, startId) {
175           console.info('ServiceAbility onCommand');
176       }
177   };
178   ```
179
180### Development in the Stage Model
181
182For details about the stage model, see [Stage Model Development Overview](../application-models/stage-model-development-overview.md).
183
1841. Configure the continuous task permission **ohos.permission.KEEP_BACKGROUND_RUNNING** in the **module.json5** file, and declare the corresponding background mode type for the ability that needs to use the task.
185
186   ```
187   "module": {
188       "abilities": [
189           {
190               "backgroundModes": [
191               "dataTransfer",
192               "location"
193               ], // Background mode
194           }
195       ],
196       "requestPermissions": [
197           {
198               "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" // Continuous task permission
199           }
200       ]
201   }
202   ```
203
2042. If an application needs to execute a continuous task for its own, include the execution logic in the Page ability. This is because an application cannot use **startAbilityByCall** to create and run its own ability in the background due to the restriction of ability startup controls.  For details, see [UIAbility Component Overview](../application-models/uiability-overview.md).
205
206   ```ts
207   import wantAgent from '@ohos.wantAgent';
208   import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
209
210   @Entry
211   @Component
212   struct Index {
213     @State message: string = 'test'
214     // Use getContext to obtain the context of the Page ability.
215     private context: any = getContext(this)
216
217     startContinuousTask() {
218       let wantAgentInfo = {
219         // List of operations to be executed after the notification is clicked.
220         wants: [
221           {
222             bundleName: "com.example.myapplication",
223             abilityName: "com.example.myapplication.MainAbility",
224           }
225         ],
226         // Type of the operation to perform after the notification is clicked.
227         operationType: wantAgent.OperationType.START_ABILITY,
228         // Custom request code.
229         requestCode: 0,
230         // Execution attribute of the operation to perform after the notification is clicked.
231         wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
232       };
233
234       // Obtain the WantAgent object by using the getWantAgent API of the wantAgent module.
235       wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
236           try {
237               backgroundTaskManager.startBackgroundRunning(this.context,
238                   backgroundTaskManager.BackgroundMode.DATA_TRANSFER, wantAgentObj).then(() => {
239                   console.info("Operation startBackgroundRunning succeeded");
240               }).catch((err) => {
241                   console.error("Operation startBackgroundRunning failed Cause: " + err);
242               });
243           } catch (error) {
244               console.error(`Operation startBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
245           }
246       });
247     }
248
249     stopContinuousTask() {
250       try {
251           backgroundTaskManager.stopBackgroundRunning(this.context).then(() => {
252           console.info("Operation stopBackgroundRunning succeeded");
253           }).catch((err) => {
254           console.error("Operation stopBackgroundRunning failed Cause: " + err);
255           });
256       } catch (error) {
257           console.error(`Operation stopBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
258       }
259     }
260
261     build() {
262       Row() {
263         Column() {
264           Text("Index")
265             .fontSize(50)
266             .fontWeight(FontWeight.Bold)
267
268           Button() { Text('Request continuous task').fontSize(25).fontWeight(FontWeight.Bold) }.type(ButtonType.Capsule)
269           .margin({ top: 10 }).backgroundColor('#0D9FFB').width(250).height(40)
270           .onClick(() => {
271             // Request a continuous task by clicking a button.
272             this.startContinuousTask();
273
274             // Execute the continuous task logic, for example, music playback.
275           })
276
277           Button() {Text('Cancel continuous task') .fontSize(25).fontWeight(FontWeight.Bold) }.type(ButtonType.Capsule)
278           .margin({ top: 10 }).backgroundColor('#0D9FFB').width(250).height(40)
279           .onClick(() => {
280             // Stop the continuous task.
281
282             // Cancel the continuous task by clicking a button.
283             this.stopContinuousTask();
284           })
285         }
286         .width('100%')
287       }
288       .height('100%')
289     }
290   }
291   ```
292
2933. If a continuous task needs to be executed in the background for another application or on another device, you can create and run an ability in the background in Call mode. For details, see [Using Call to Implement UIAbility Interaction (intra-device)](../application-models/uiability-intra-device-interaction.md#using-call-to-implement-uiability-interaction-for-system-applications-only) and [Using Cross-Device Call (inter-device)](../application-models/hop-multi-device-collaboration.md#using-cross-device-call).
294
295   ```ts
296   import UIAbility from '@ohos.app.ability.UIAbility';
297   import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
298   import wantAgent from '@ohos.wantAgent';
299
300   const MSG_SEND_METHOD: string = 'CallSendMsg'
301
302   let mContext = null;
303
304   function startContinuousTask() {
305       let wantAgentInfo = {
306           // List of operations to be executed after the notification is clicked.
307           wants: [
308               {
309                   bundleName: "com.example.myapplication",
310                   abilityName: "com.example.myapplication.MainAbility",
311               }
312           ],
313           // Type of the operation to perform after the notification is clicked.
314           operationType: wantAgent.OperationType.START_ABILITY,
315           // Custom request code.
316           requestCode: 0,
317           // Execution attribute of the operation to perform after the notification is clicked.
318           wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
319       };
320
321       // Obtain the WantAgent object by using the getWantAgent API of the wantAgent module.
322       wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
323           try {
324               backgroundTaskManager.startBackgroundRunning(mContext,
325                   backgroundTaskManager.BackgroundMode.DATA_TRANSFER, wantAgentObj).then(() => {
326                   console.info("Operation startBackgroundRunning succeeded");
327               }).catch((error) => {
328                   console.error(`Operation startBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
329               });
330           } catch (error) {
331               console.error(`Operation startBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
332           }
333       });
334   }
335
336   function stopContinuousTask() {
337       try {
338           backgroundTaskManager.stopBackgroundRunning(mContext).then(() => {
339               console.info("Operation stopBackgroundRunning succeeded");
340           }).catch((error) => {
341               console.error(`Operation stopBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
342           });
343       } catch (error) {
344           console.error(`Operation stopBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
345       }
346   }
347
348   class MyParcelable {
349       num: number = 0;
350       str: String = "";
351
352       constructor(num, string) {
353           this.num = num;
354           this.str = string;
355       }
356
357       marshalling(messageSequence) {
358           messageSequence.writeInt(this.num);
359           messageSequence.writeString(this.str);
360           return true;
361       }
362
363       unmarshalling(messageSequence) {
364           this.num = messageSequence.readInt();
365           this.str = messageSequence.readString();
366           return true;
367       }
368   }
369
370   function sendMsgCallback(data) {
371       console.info('BgTaskAbility funcCallBack is called ' + data)
372       let receivedData = new MyParcelable(0, "")
373       data.readParcelable(receivedData)
374       console.info(`receiveData[${receivedData.num}, ${receivedData.str}]`)
375       // You can execute different methods based on the str value in the parcelable data sent by the caller.
376       if (receivedData.str === 'start_bgtask') {
377           startContinuousTask()
378       } else if (receivedData.str === 'stop_bgtask') {
379           stopContinuousTask();
380       }
381       return new MyParcelable(10, "Callee test");
382   }
383
384   export default class BgTaskAbility extends Ability {
385       onCreate(want, launchParam) {
386           console.info("[Demo] BgTaskAbility onCreate")
387           this.callee.on("test", sendMsgCallback);
388
389           try {
390               this.callee.on(MSG_SEND_METHOD, sendMsgCallback)
391           } catch (error) {
392               console.error(`${MSG_SEND_METHOD} register failed with error ${JSON.stringify(error)}`)
393           }
394           mContext = this.context;
395       }
396
397       onDestroy() {
398           console.info("[Demo] BgTaskAbility onDestroy")
399       }
400
401       onWindowStageCreate(windowStage) {
402           console.info("[Demo] BgTaskAbility onWindowStageCreate")
403
404           windowStage.loadContent("pages/index").then((data)=> {
405               console.info(`load content succeed with data ${JSON.stringify(data)}`)
406           }).catch((error)=>{
407               console.error(`load content failed with error ${JSON.stringify(error)}`)
408           })
409       }
410
411       onWindowStageDestroy() {
412           console.info("[Demo] BgTaskAbility onWindowStageDestroy")
413       }
414
415       onForeground() {
416           console.info("[Demo] BgTaskAbility onForeground")
417       }
418
419       onBackground() {
420           console.info("[Demo] BgTaskAbility onBackground")
421       }
422   };
423   ```
424
425