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