• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ContinuationManager开发指导
2
3> 说明:本模块接口用于拉起系统中的设备选择模块,由于该模块功能暂不完备,因此**流转能力整体暂不支持用于应用开发**。
4
5## 场景简介
6随着全场景多设备生活方式的不断深入,用户拥有的设备越来越多,每个设备都能在适合的场景下提供良好的体验,但是,每个设备也有使用场景的局限。流转能力致力于打破设备界限,多设备联动,使用户应用程序可分可合、可流转,实现体验升级。
7
8continuationManager作为流转能力的入口,主要用于拉起系统中的设备选择模块供用户选择,待选择设备后,会给用户返回已选择的远端设备信息,用户可以根据远端设备信息发起跨端迁移或多端协同操作。
9
10![continuationManager](figures/continuationManager.png)
11
12## 接口说明
13| 接口名                                                                                          | 接口描述 |
14| ---------------------------------------------------------------------------------------------- | ----------- |
15| registerContinuation(callback: AsyncCallback\<number>): void | 注册流转管理服务,并获取对应的注册token,无过滤条件(AsyncCallback)。 |
16| registerContinuation(options: ContinuationExtraParams, callback: AsyncCallback\<number>): void | 注册流转管理服务,并获取对应的注册token(AsyncCallback)。 |
17| registerContinuation(options?: ContinuationExtraParams): Promise\<number> | 连接流转管理服务,并获取对应的注册token(Promise)。 |
18| on(type: "deviceSelected", token: number, callback: Callback\<Array\<ContinuationResult>>): void | 监听设备连接状态(Callback)。 |
19| on(type: "deviceUnselected", token: number, callback: Callback\<Array\<ContinuationResult>>): void | 监听设备断开状态(Callback)。 |
20| off(type: "deviceSelected", token: number): void | 取消监听设备连接状态。 |
21| off(type: "deviceUnselected", token: number): void | 取消监听设备断开状态。 |
22| startContinuationDeviceManager(token: number, callback: AsyncCallback\<void>): void | 拉起设备选择模块,可显示组网内可选择设备列表信息,无过滤条件(AsyncCallback)。 |
23| startContinuationDeviceManager(token: number, options: ContinuationExtraParams, callback: AsyncCallback\<void>): void | 拉起设备选择模块,可显示组网内可选择设备列表信息(AsyncCallback)。 |
24| startContinuationDeviceManager(token: number, options?: ContinuationExtraParams): Promise\<void> | 拉起设备选择模块,可显示组网内可选择设备列表信息(Promise)。 |
25| updateContinuationState(token: number, deviceId: string, status: DeviceConnectState, callback: AsyncCallback\<void>): void | 通知设备选择模块,更新当前的流转状态(AsyncCallback)。 |
26| updateContinuationState(token: number, deviceId: string, status: DeviceConnectState): Promise\<void> | 通知设备选择模块,更新当前的流转状态(Promise)。 |
27| unregisterContinuation(token: number, callback: AsyncCallback\<void>): void | 取消注册流转管理服务,传入注册时获取的token进行取消注册(AsyncCallback)。 |
28| unregisterContinuation(token: number): Promise\<void> | 取消注册流转管理服务,传入注册时获取的token进行取消注册(Promise)。 |
29
30## 开发步骤
311. 导入continuationManager模块。
32
33    ```ts
34    import continuationManager from '@ohos.continuation.continuationManager';
35    ```
36
372. 申请分布式权限 DISTRIBUTED_DATASYNC。
38
39    权限申请在FA平台和Stage平台有区别,FA平台需要在`config.json`里面进行配置请求权限,示例代码如下:
40
41    ```json
42    {
43        "module": {
44            "reqPermissions": [
45                {
46                    "name": "ohos.permission.DISTRIBUTED_DATASYNC"
47                }
48            ]
49        }
50    }
51    ```
52
53    这个权限还需要在应用首次启动的时候弹窗获取用户授权,可以通过如下代码实现:
54
55    ```ts
56    import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
57    import bundle from '@ohos.bundle';
58    import featureAbility from '@ohos.ability.featureAbility';
59
60    async function requestPermission() {
61        let permissions: Array<string> = [
62            "ohos.permission.DISTRIBUTED_DATASYNC"
63        ];
64        let needGrantPermission: boolean = false;
65        let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
66        let applicationInfo = await bundle.getApplicationInfo('ohos.samples.etsDemo', 0, 100);
67        for (let i = 0; i < permissions.length; i++) {
68            let result = await atManager.verifyAccessToken(applicationInfo.accessTokenId, permissions[i]);
69            //判断是否未申请该权限
70            if (result == abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
71                needGrantPermission = true;
72                break;
73            }
74        }
75        // 如果未申请该权限,则需要调用requestPermissionsFromUser接口申请权限
76        if (needGrantPermission) {
77            await featureAbility.getContext().requestPermissionsFromUser(permissions, 1);
78        } else {
79            console.info('app permission already granted');
80        }
81    }
82    ```
83
84    Stage平台需要在`module.json5`里面进行配置请求权限,示例代码如下:
85
86    ```json
87    {
88        "module": {
89            "requestPermissions": [
90                {
91                    "name": "ohos.permission.DISTRIBUTED_DATASYNC"
92                }
93            ]
94        }
95    }
96    ```
97
98    ```ts
99    import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
100    import bundle from '@ohos.bundle';
101
102    async function requestPermission() {
103        let permissions: Array<string> = [
104            "ohos.permission.DISTRIBUTED_DATASYNC"
105        ];
106        let needGrantPermission: boolean = false;
107        let atManger: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
108        let applicationInfo = await bundle.getApplicationInfo('ohos.samples.continuationmanager', 0, 100);
109        for (const permission of permissions) {
110            try {
111                let grantStatus = await atManger.verifyAccessToken(applicationInfo.accessTokenId, permission);
112                //判断是否未申请该权限
113                if (grantStatus === abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {
114                    needGrantPermission = true;
115                    break;
116                }
117            } catch (err) {
118                console.error('app permission query grant status error' + JSON.stringify(err));
119                needGrantPermission = true;
120                break;
121            }
122        }
123        // 如果未申请该权限,则需要调用requestPermissionsFromUser接口申请权限
124        if (needGrantPermission) {
125            try {
126                // globalThis.contextAbility.context,需提前在MainAbility.ts文件中赋值
127                await atManger.requestPermissionsFromUser(globalThis.context, permissions);
128            } catch (err) {
129                console.error('app permission request permissions error' + JSON.stringify(err));
130            }
131        } else {
132            console.info('app permission already granted');
133        }
134    }
135    ```
136
1373. 注册流转管理服务,获取对应的注册token。
138
139    注册流转管理服务的代码示例如下:
140
141    ```ts
142    let token: number = -1; // 用于保存注册成功并返回的token,后续使用其完成监听设备连接/断开状态、拉起设备选择模块以及更新流转状态的动作
143    try {
144        continuationManager.registerContinuation().then((data) => {
145            console.info('registerContinuation finished, ' + JSON.stringify(data));
146            token = data; // 获取到对应的注册token,并赋值给token变量
147        }).catch((err) => {
148            console.error('registerContinuation failed, cause: ' + JSON.stringify(err));
149        });
150    } catch (err) {
151        console.error('registerContinuation failed, cause: ' + JSON.stringify(err));
152    }
153    ```
154
1554. 监听设备状态。
156
157    监听设备连接状态的代码示例如下:
158
159    ```ts
160    let remoteDeviceId: string = ""; // 用于保存用户选择的远端设备信息,后续使用其完成跨端迁移或多端协同操作
161
162    try {
163        // 参数token为注册token
164        continuationManager.on("deviceSelected", token, (continuationResults) => {
165            console.info('registerDeviceSelectedCallback len: ' + continuationResults.length);
166            if (continuationResults.length <= 0) {
167                console.info('no selected device');
168                return;
169            }
170            remoteDeviceId = continuationResults[0].id; // 将选择的第一个远端设备deviceId赋值给remoteDeviceId变量
171
172            // 将remoteDeviceId参数传给want
173            let want = {
174                deviceId: remoteDeviceId,
175                bundleName: 'ohos.samples.continuationmanager',
176                abilityName: 'MainAbility'
177            };
178            globalThis.abilityContext.startAbility(want).then((data) => {
179                console.info('StartRemoteAbility finished, ' + JSON.stringify(data));
180            }).catch((err) => {
181                console.error('StartRemoteAbility failed, cause: ' + JSON.stringify(err));
182            });
183        });
184    } catch (err) {
185        console.error('on failed, cause: ' + JSON.stringify(err));
186    }
187    ```
188
189    上述多端协同操作为Stage平台的跨设备拉起,FA平台详情见[PageAbility开发指导](fa-pageability.md)。
190
191    同时用户还可通知设备选择模块,更新当前的流转状态,代码示例如下:
192
193    ```ts
194    // 设置设备流转状态
195    let deviceConnectStatus: continuationManager.DeviceConnectState = continuationManager.DeviceConnectState.CONNECTED;
196
197    // 参数token为注册token,参数remoteDeviceId为获取到的remoteDeviceId
198    try {
199        continuationManager.updateContinuationState(token, remoteDeviceId, deviceConnectStatus).then((data) => {
200            console.info('updateContinuationState finished, ' + JSON.stringify(data));
201        }).catch((err) => {
202            console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
203        });
204    } catch (err) {
205        console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
206    }
207    ```
208
209    监听设备断开状态,方便用户终止跨端迁移或多端协同操作,代码示例如下:
210
211    ```ts
212    try {
213        // 参数token为注册token
214        continuationManager.on("deviceUnselected", token, (continuationResults) => {
215            console.info('onDeviceUnselected len: ' + continuationResults.length);
216            if (continuationResults.length <= 0) {
217                console.info('no unselected device');
218                return;
219            }
220
221            // 更新设备流转状态
222            let unselectedDeviceId: string = continuationResults[0].id; // 将取消选择的第一个远端设备deviceId赋值给unselectedDeviceId变量
223            let deviceConnectStatus: continuationManager.DeviceConnectState = continuationManager.DeviceConnectState.DISCONNECTING; // 设备断开状态
224
225            // 参数token为注册token,参数unselectedDeviceId为获取到的unselectedDeviceId
226            continuationManager.updateContinuationState(token, unselectedDeviceId, deviceConnectStatus).then((data) => {
227                console.info('updateContinuationState finished, ' + JSON.stringify(data));
228            }).catch((err) => {
229                console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
230            });
231        });
232    } catch (err) {
233        console.error('updateContinuationState failed, cause: ' + JSON.stringify(err));
234    }
235    ```
236
2375. 拉起设备选择模块,可显示组网内可选择设备列表信息,供用户选择。
238
239    拉起设备选择模块的代码示例如下:
240
241    ```ts
242    // 过滤参数
243    let continuationExtraParams = {
244        deviceType: ["00E"], // 设备类型
245        continuationMode: continuationManager.ContinuationMode.COLLABORATION_SINGLE // 设备选择模块单选模式
246    };
247
248    try {
249        // 参数token为注册token
250        continuationManager.startContinuationDeviceManager(token, continuationExtraParams).then((data) => {
251            console.info('startContinuationDeviceManager finished, ' + JSON.stringify(data));
252        }).catch((err) => {
253            console.error('startContinuationDeviceManager failed, cause: ' + JSON.stringify(err));
254        });
255    } catch (err) {
256        console.error('startContinuationDeviceManager failed, cause: ' + JSON.stringify(err));
257    }
258    ```
259
2606. 当用户不打算再进行跨端迁移或多端协同操作时,可以传入注册时获取的token进行取消注册。
261
262    取消注册流转管理服务的代码示例如下:
263
264    ```ts
265    try {
266        // 参数token为注册token
267        continuationManager.unregisterContinuation(token).then((data) => {
268            console.info('unregisterContinuation finished, ' + JSON.stringify(data));
269        }).catch((err) => {
270            console.error('unregisterContinuation failed, cause: ' + JSON.stringify(err));
271        });
272    } catch (err) {
273        console.error('unregisterContinuation failed, cause: ' + JSON.stringify(err));
274    }
275    ```