• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ContinuationManager Development
2
3> **NOTE**
4>
5> Currently, the **ContinuationManager** module is not available for application development. Its APIs are mainly used to start the device selection module.
6
7## When to Use
8Users are using two or more devices to experience an all-scenario, multi-device lifestyle. Each type of device has its unique advantages and disadvantages specific to scenarios. The ability continuation capability breaks boundaries of devices and enables multi-device collaboration, achieving precise control, universal coordination, and seamless hops of user applications.
9
10As the entry of the ability continuation capability, **continuationManager** is used to start the device selection module for the user to select the target device. After a device is selected, information about the selected device is returned to the user. The user can then initiate cross-device continuation or collaboration based on the device information.
11
12![continuationManager](figures/continuationManager.png)
13
14## Available APIs
15| API                                                                                         | Description|
16| ---------------------------------------------------------------------------------------------- | ----------- |
17| registerContinuation(callback: AsyncCallback\<number>): void | Registers the continuation management service and obtains a token. This API does not involve any filter parameters and uses an asynchronous callback to return the result.|
18| registerContinuation(options: ContinuationExtraParams, callback: AsyncCallback\<number>): void | Registers the continuation management service and obtains a token. This API uses an asynchronous callback to return the result.|
19| registerContinuation(options?: ContinuationExtraParams): Promise\<number> | Registers the continuation management service and obtains a token. This API uses a promise to return the result.|
20| on(type: "deviceSelected", token: number, callback: Callback\<Array\<ContinuationResult>>): void | Subscribes to device connection events. This API uses an asynchronous callback to return the result.|
21| on(type: "deviceUnselected", token: number, callback: Callback\<Array\<ContinuationResult>>): void | Subscribes to device disconnection events. This API uses an asynchronous callback to return the result.|
22| off(type: "deviceSelected", token: number): void | Unsubscribes from device connection events.|
23| off(type: "deviceUnselected", token: number): void | Unsubscribes from device disconnection events.|
24| startContinuationDeviceManager(token: number, callback: AsyncCallback\<void>): void | Starts the device selection module to show the list of available devices. This API does not involve any filter parameters and uses an asynchronous callback to return the result.|
25| startContinuationDeviceManager(token: number, options: ContinuationExtraParams, callback: AsyncCallback\<void>): void | Starts the device selection module to show the list of available devices. This API uses an asynchronous callback to return the result.|
26| startContinuationDeviceManager(token: number, options?: ContinuationExtraParams): Promise\<void> | Starts the device selection module to show the list of available devices. This API uses a promise to return the result.|
27| updateContinuationState(token: number, deviceId: string, status: DeviceConnectState, callback: AsyncCallback\<void>): void | Instructs the device selection module to update the device connection state. This API uses an asynchronous callback to return the result.|
28| updateContinuationState(token: number, deviceId: string, status: DeviceConnectState): Promise\<void> | Instructs the device selection module to update the device connection state. This API uses a promise to return the result.|
29| unregisterContinuation(token: number, callback: AsyncCallback\<void>): void | Deregisters the continuation management service. This API uses an asynchronous callback to return the result.|
30| unregisterContinuation(token: number): Promise\<void> | Deregisters the continuation management service. This API uses a promise to return the result.|
31
32## How to Develop
331. Import the **continuationManager** module.
34
35    ```ts
36    import continuationManager from '@ohos.continuation.continuationManager';
37    ```
38
392. Apply for the **DISTRIBUTED_DATASYNC** permission.
40
41    The permission application operation varies according to the ability model in use. In the FA mode, add the required permission in the `config.json` file, as follows:
42
43    ```json
44    {
45        "module": {
46            "reqPermissions": [
47                {
48                    "name": "ohos.permission.DISTRIBUTED_DATASYNC"
49                }
50            ]
51        }
52    }
53    ```
54
55    This permission must also be granted by the user through a dialog box when the application is started for the first time. The sample code is as follows:
56
57    ```ts
58    import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
59    import bundle from '@ohos.bundle';
60    import featureAbility from '@ohos.ability.featureAbility';
61
62    async function requestPermission() {
63        let permissions: Array<string> = [
64            "ohos.permission.DISTRIBUTED_DATASYNC"
65        ];
66        let needGrantPermission: boolean = false;
67        let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
68        let applicationInfo = await bundle.getApplicationInfo('ohos.samples.etsDemo', 0, 100);
69        for (let i = 0; i < permissions.length; i++) {
70            let result = await atManager.verifyAccessToken(applicationInfo.accessTokenId, permissions[i]);
71            // Check whether the permission is granted.
72            if (result == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
73                needGrantPermission = true;
74                break;
75            }
76        }
77        // If the permission is not granted, call requestPermissionsFromUser to apply for the permission.
78        if (needGrantPermission) {
79            await featureAbility.getContext().requestPermissionsFromUser(permissions, 1);
80        } else {
81            console.info('app permission already granted');
82        }
83    }
84    ```
85
86    In the stage model, add the required permission in the `module.json5` file. The sample code is as follows:
87
88    ```json
89    {
90        "module": {
91            "requestPermissions": [
92                {
93                    "name": "ohos.permission.DISTRIBUTED_DATASYNC"
94                }
95            ]
96        }
97    }
98    ```
99
100    ```ts
101    import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
102    import bundle from '@ohos.bundle';
103
104    async function requestPermission() {
105        let permissions: Array<string> = [
106            "ohos.permission.DISTRIBUTED_DATASYNC"
107        ];
108        let needGrantPermission: boolean = false;
109        let atManger: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
110        let applicationInfo = await bundle.getApplicationInfo('ohos.samples.continuationmanager', 0, 100);
111        for (const permission of permissions) {
112            try {
113                let grantStatus = await atManger.verifyAccessToken(applicationInfo.accessTokenId, permission);
114                // Check whether the permission is granted.
115                if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {
116                    needGrantPermission = true;
117                    break;
118                }
119            } catch (err) {
120                console.error('app permission query grant status error' + JSON.stringify(err));
121                needGrantPermission = true;
122                break;
123            }
124        }
125        // If the permission is not granted, call requestPermissionsFromUser to apply for the permission.
126        if (needGrantPermission) {
127            try {
128                // globalThis.context is Ability.context, which must be assigned a value in the MainAbility.ts file in advance.
129                await atManger.requestPermissionsFromUser(globalThis.context, permissions);
130            } catch (err) {
131                console.error('app permission request permissions error' + JSON.stringify(err));
132            }
133        } else {
134            console.info('app permission already granted');
135        }
136    }
137    ```
138
1393. Register the continuation management service and obtain a token.
140
141    The sample code is as follows:
142
143    ```ts
144    let token: number = -1; // Used to save the token returned after the registration. The token will be used when listening for device connection/disconnection events, starting the device selection module, and updating the device connection state.
145    try {
146        continuationManager.registerContinuation().then((data) => {
147            console.info('registerContinuation finished, ' + JSON.stringify(data));
148            token = data; // Obtain a token and assign a value to the token variable.
149        }).catch((err) => {
150            console.error('registerContinuation failed, cause: ' + JSON.stringify(err));
151        });
152    } catch (err) {
153        console.error('registerContinuation failed, cause: ' + JSON.stringify(err));
154    }
155    ```
156
1574. Listen for the device connection/disconnection state.
158
159    The sample code is as follows:
160
161    ```ts
162    let remoteDeviceId: string = ""; // Used to save the information about the remote device selected by the user, which will be used for cross-device continuation or collaboration.
163
164    try {
165        // The token parameter is the token obtained during the registration.
166        continuationManager.on("deviceSelected", token, (continuationResults) => {
167            console.info('registerDeviceSelectedCallback len: ' + continuationResults.length);
168            if (continuationResults.length <= 0) {
169                console.info('no selected device');
170                return;
171            }
172            remoteDeviceId = continuationResults[0].id; // Assign the deviceId of the first selected remote device to the remoteDeviceId variable.
173
174            // Pass the remoteDeviceId parameter to want.
175            let want = {
176                deviceId: remoteDeviceId,
177                bundleName: 'ohos.samples.continuationmanager',
178                abilityName: 'MainAbility'
179            };
180            globalThis.abilityContext.startAbility(want).then((data) => {
181                console.info('StartRemoteAbility finished, ' + JSON.stringify(data));
182            }).catch((err) => {
183                console.error('StartRemoteAbility failed, cause: ' + JSON.stringify(err));
184            });
185        });
186    } catch (err) {
187        console.error('on failed, cause: ' + JSON.stringify(err));
188    }
189    ```
190
191    The preceding multi-device collaboration operation is performed across devices in the stage model. For details about this operation in the FA model, see [Page Ability Development](fa-pageability.md).
192
193    You can also instruct the device selection module to update the device connection state. The sample code is as follows:
194
195    ```ts
196    // Set the device connection state.
197    let deviceConnectStatus: continuationManager.DeviceConnectState = continuationManager.DeviceConnectState.CONNECTED;
198
199    // The token parameter is the token obtained during the registration, and the remoteDeviceId parameter is the remoteDeviceId obtained.
200    try {
201        continuationManager.updateContinuationState(token, remoteDeviceId, deviceConnectStatus).then((data) => {
202            console.info('updateContinuationState finished, ' + JSON.stringify(data));
203        }).catch((err) => {
204            console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
205        });
206    } catch (err) {
207        console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
208    }
209    ```
210
211    Listen for the device disconnection state so that the user can stop cross-device continuation or collaboration in time. The sample code is as follows:
212
213    ```ts
214    try {
215        // The token parameter is the token obtained during the registration.
216        continuationManager.on("deviceUnselected", token, (continuationResults) => {
217            console.info('onDeviceUnselected len: ' + continuationResults.length);
218            if (continuationResults.length <= 0) {
219                console.info('no unselected device');
220                return;
221            }
222
223            // Update the device connection state.
224            let unselectedDeviceId: string = continuationResults[0].id; // Assign the deviceId of the first deselected remote device to the unselectedDeviceId variable.
225            let deviceConnectStatus: continuationManager.DeviceConnectState = continuationManager.DeviceConnectState.DISCONNECTING; // Device disconnected.
226
227            // The token parameter is the token obtained during the registration, and the unselectedDeviceId parameter is the unselectedDeviceId obtained.
228            continuationManager.updateContinuationState(token, unselectedDeviceId, deviceConnectStatus).then((data) => {
229                console.info('updateContinuationState finished, ' + JSON.stringify(data));
230            }).catch((err) => {
231                console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
232            });
233        });
234    } catch (err) {
235        console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
236    }
237    ```
238
2395. Start the device selection module to show the list of available devices on the network.
240
241    The sample code is as follows:
242
243    ```ts
244    // Filter parameters.
245    let continuationExtraParams = {
246        deviceType: ["00E"], // Device type.
247        continuationMode: continuationManager.ContinuationMode.COLLABORATION_SINGLE // Single-choice mode of the device selection module.
248    };
249
250    try {
251        // The token parameter is the token obtained during the registration.
252        continuationManager.startContinuationDeviceManager(token, continuationExtraParams).then((data) => {
253            console.info('startContinuationDeviceManager finished, ' + JSON.stringify(data));
254        }).catch((err) => {
255            console.error('startContinuationDeviceManager failed, cause: ' + JSON.stringify(err));
256        });
257    } catch (err) {
258        console.error('startContinuationDeviceManager failed, cause: ' + JSON.stringify(err));
259    }
260    ```
261
2626. If you do not need to perform cross-device migration or collaboration operations, you can deregister the continuation management service, by passing the token obtained during the registration.
263
264    The sample code is as follows:
265
266    ```ts
267    try {
268        // The token parameter is the token obtained during the registration.
269        continuationManager.unregisterContinuation(token).then((data) => {
270            console.info('unregisterContinuation finished, ' + JSON.stringify(data));
271        }).catch((err) => {
272            console.error('unregisterContinuation failed, cause: ' + JSON.stringify(err));
273        });
274    } catch (err) {
275        console.error('unregisterContinuation failed, cause: ' + JSON.stringify(err));
276    }
277    ```
278