• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Ability Continuation Development
2
3## When to Use
4
5Ability continuation is to continue the current mission of an application, including the UI component state variables and distributed objects, on another device. The UI component state variables are used to synchronize UI data, and the distributed objects are used to synchronize memory data.
6
7## Available APIs
8
9The following table lists the APIs used for ability continuation. For details about the APIs, see [Ability](../reference/apis/js-apis-application-ability.md).
10
11**Table 1** Ability continuation APIs
12
13|API| Description|
14|:------ | :------|
15| onContinue(wantParam : {[key: string]: any}): OnContinueResult | Called by the initiator to store the data required for continuation and request continuation. The value **AGREE** means that the continuation is accepted, and **REJECT** means the continuation is rejected, and **MISMATCH** means a version mismatch.|
16| onCreate(want: Want, param: LaunchParam): void | Called by the target to restore the data and UI page.|
17| **enum** OnContinueResult | Enumerates the return values of **onContinue**. The options are as follows: **AGREE** (request accepted), **REJECT** (request denied), and **MISMATCH** (version mismatch).|
18
19
20
21**Figure 1** Ability continuation development
22
23![continuation_dev](figures/continuation-info.png)
24
25## How to Develop
26
27### Application Continuation
28
291. Configuration
30
31   - Configure the application to support ability continuation.
32
33     Set the **continuable** field in the **module.json5** file to **true**. The default value is **false**. If this parameter is set to **false**, the application cannot be continued on another device.
34
35   ```javascript
36   "continuable": true
37   ```
38
39
40
41   - Configure the application startup type.
42
43     Set **launchType** in the **module.json5** file to **standard** to add multi-instance support to the application.
44
45   ```javascript
46   "launchType": "standard"
47   ```
48
49
50
51   - Apply for the distributed permissions.
52
53     Declare the **DISTRIBUTED_DATASYNC** permission in the **module.json5** file for the application.
54
55   ```javascript
56   "requestPermissions": [
57       {
58           "name": "ohos.permission.DISTRIBUTED_DATASYNC"
59       },
60   ```
61
62   This permission must be granted by the user in a dialog box when the application is started for the first time. To enable the application to display a dialog box to ask for the permission, add the following code to **onWindowStageCreate** of the **Ability** class:
63
64   ```javascript
65   requestPermissions = async () => {
66       let permissions: Array<string> = [
67           "ohos.permission.DISTRIBUTED_DATASYNC"
68       ];
69       let needGrantPermission = false
70       let accessManger = accessControl.createAtManager()
71       Logger.info("app permission get bundle info")
72       let bundleInfo = await bundle.getApplicationInfo(BUNDLE_NAME, 0, 100)
73       Logger.info(`app permission query permission ${bundleInfo.accessTokenId.toString()}`)
74       for (const permission of permissions) {
75           Logger.info(`app permission query grant status ${permission}`)
76           try {
77               let grantStatus = await accessManger.verifyAccessToken(bundleInfo.accessTokenId, permission)
78               if (grantStatus === PERMISSION_REJECT) {
79                   needGrantPermission = true
80                   break;
81               }
82           } catch (err) {
83               Logger.error(`app permission query grant status error ${permission} ${JSON.stringify(err)}`)
84               needGrantPermission = true
85               break;
86           }
87       }
88       if (needGrantPermission) {
89           Logger.info("app permission needGrantPermission")
90           try {
91               await this.context.requestPermissionsFromUser(permissions)
92           } catch (err) {
93               Logger.error(`app permission ${JSON.stringify(err)}`)
94           }
95       } else {
96           Logger.info("app permission already granted")
97       }
98   }
99   ```
100
101
102
1032. Implement the **onContinue()** API.
104
105   The **onContinue()** API is called by the initiator to save the UI component state variables and memory data and prepare for continuation. After the application completes the continuation preparation, the system must return **OnContinueResult.AGREE(0)** to accept the continuation request. If an error code is returned, the request is rejected. If this API is not implemented, the system rejects the continuation request by default.
106
107   Modules to import:
108
109   ```javascript
110   import Ability from '@ohos.application.Ability';
111   import AbilityConstant from '@ohos.application.AbilityConstant';
112   ```
113
114   To implement ability continuation, you must implement this API and have the value **AGREE** returned.
115
116
117   Example
118
119   ```javascript
120    onContinue(wantParam : {[key: string]: any}) {
121        Logger.info("onContinue using distributedObject")
122        // Set the user input data into want params.
123        wantParam["input"] = AppStorage.Get<string>('ContinueInput');
124        Logger.info(`onContinue input = ${wantParam["input"]}`);
125        return AbilityConstant.OnContinueResult.AGREE
126    }
127   ```
128
129
130
1313. Implement the continuation logic in the **onCreate()** API.
132
133   The **onCreate()** API is called by the target. When the ability is started on the target device, this API is called to instruct the application to synchronize the memory data and UI component state, and triggers page restoration after the synchronization is complete. If the continuation logic is not implemented, the ability will be started in common startup mode and the page cannot be restored.
134
135   The target device determines whether the startup is **LaunchReason.CONTINUATION** based on **launchReason** in **onCreate()**.
136
137
138   After data restore is complete, call **restoreWindowStage** to trigger page restoration.
139
140
141   Example
142
143   ```javascript
144       onCreate(want, launchParam) {
145           Logger.info(`MainAbility onCreate ${AbilityConstant.LaunchReason.CONTINUATION}`)
146           globalThis.abilityWant = want;
147           if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
148               let input = want.parameters.input // Obtain user data from want params.
149               AppStorage.SetOrCreate<string>('ContinueInput', input)
150               Logger.info(`onCreate for continuation sessionId:  ${this.sessionId}`)
151
152               this.contentStorage = new ContentStorage();
153               this.context.restoreWindowStage(this.contentStorage);
154           }
155       }
156   ```
157
158
159
160### Data Continuation
161
162Use distributed objects.
163
164Distributed objects allow cross-device data synchronization like local variables. For two devices that form a Super Device, when data in the distributed data object of an application is added, deleted, or modified on a device, the data for the same application is also updated on the other device. Both devices can listen for the data changes and online and offline states of the other. For details, see [Distributed Data Object Development](../database/database-distributedobject-guidelines.md).
165
166In the ability continuation scenario, the distributed data object is used to synchronize the memory data from the local device to the target device.
167
168- In **onContinue()**, the initiator saves the data to be continued to the distributed object, sets the session ID, and sends the session ID to the target device through **wantParam**.
169
170    ```javascript
171      import Ability from '@ohos.application.Ability';
172      import distributedObject from '@ohos.data.distributedDataObject';
173
174      var g_object = distributedObject.createDistributedObject({name:undefined});
175
176      export default class MainAbility extends Ability {
177          contentStorage : ContentStorage
178          sessionId : string;
179
180       onContinue(wantParam : {[key: string]: any}) {
181           Logger.info("onContinue using distributedObject")
182           this.sessionId = distributedObject.genSessionId();
183           // Set the session ID for the distributed data object.
184           g_object.setSessionId(this.sessionId);
185           g_object.name = "Amy";
186           // Set the session ID into the want parameter.
187           wantParam["session"] = this.sessionId;
188           return AbilityConstant.OnContinueResult.AGREE
189       }
190
191    ```
192
193- The target device obtains the session ID from **onCreate()**, creates a distributed object, and associates the distributed object with the session ID. In this way, the distributed object can be synchronized. Before calling **restoreWindowStage**, ensure that all distributed objects required for continuation have been associated.
194
195   ```javascript
196      import Ability from '@ohos.application.Ability';
197      import distributedObject from '@ohos.data.distributedDataObject';
198
199      var g_object = distributedObject.createDistributedObject({name:undefined});
200
201      export default class MainAbility extends Ability {
202          contentStorage : ContentStorage
203          sessionId : string;
204
205          statusCallback(sessionId, networkid, status) {
206              Logger.info(`continuation object status change, sessionId: ${sessionId}, status: ${status}, g_object.name: ${g_object.name}`)
207          }
208
209          onCreate(want, launchParam) {
210              Logger.info(`MainAbility onCreate ${AbilityConstant.LaunchReason.CONTINUATION}`)
211              if (launchParam.launchReason == AbilityConstant.LaunchReason.CONTINUATION) {
212                  // Obtain the session ID of the distributed data object from the want parameter.
213                  this.sessionId = want.parameters.session
214                  Logger.info(`onCreate for continuation sessionId:  ${this.sessionId}`)
215
216                  g_object.on("status", this.statusCallback);
217                  // Set the session ID for data synchronization.
218                  g_object.setSessionId(this.sessionId);
219
220                  this.contentStorage = new ContentStorage();
221                  this.context.restoreWindowStage(this.contentStorage);
222              }
223          }
224      }
225   ```
226
227
228
229For details about the complete example, see the sample.
230
231
232
233