写点什么

【HarmonyOS 6】UIAbility 跨设备连接详解(分布式软总线运用)

作者:GeorgeGcs
  • 2025-11-24
    四川
  • 本文字数:3898 字

    阅读完需:约 13 分钟

【HarmonyOS 6】UIAbility跨设备连接详解(分布式软总线运用)

【HarmonyOS 6】UIAbility 跨设备连接详解(分布式软总线运用)

一、前言

我对于分布式软总线相当的亲切。2022 年搞开源鸿蒙的时候,就经常和分布式软总线打交道。在 HarmonyOS 中,UIAbility 跨设备连接,其实就是对底层开源鸿蒙,分布式软总线的能力封装。

二、首先理解跨设备链接的步骤


首先由 Distributed Service Kit 提供该能力的封装。


在进行跨设备链接之前,我们要对设备进行互信操作。这个在鸿蒙里叫做分布式设备管理,包含了设备的发现,配对,可信查询,解除配对等。详情可参见我之前写的文章:【HarmonyOS 5】鸿蒙分布式协同应用开发详解


进行完上面的可信操作,我们才能对于设备间的链接通信做处理。

三、专有名词理解:

DMS(Distributedsched Management Service):分布式组件管理框架,相当于跨设备协同的“中间人”,负责管理组件和建立连接


UIAbility:应用的界面交互核心,管生命周期、用户交互和界面渲染,跨设备协同本质就是两台设备的 UIAbility 在“对话”

四、环境准备步骤

工欲善其事,先把环境搭好:1、硬件:两台能登录华为账号的设备(A 和 B),需要支持 API 182、开发工具:DevEco Studio 4.1 及以上,public-SDK 更新到 API 18+3、设备连接:用 USB 线把两台设备连到 PC,打开蓝牙让设备互相识别组网 4、验证组网:PC 端执行 shell 命令,显示“remote device num = 1”就是组网成功


hdc shellhidumper -s 4700 -a "buscenter -l remote_device_info"
复制代码


也可通过前置步骤的分布式设备管理,来验证设备的可信。

五、源码步骤拆解:

1、 导入核心模块

首先要导入分布式服务相关的 Kit,不管是发起端还是接收端都需要:


import { abilityConnectionManager, distributedDeviceManager } from '@kit.DistributedServiceKit';import { common, AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';import { hilog } from '@kit.PerformanceAnalysisKit';
复制代码

2、 发现目标设备(设备 A 侧)

设备 A 要先找到设备 B 的 networkId,作为连接的关键参数:


let dmClass: distributedDeviceManager.DeviceManager;
// 初始化设备管理实例function initDmClass(): void { try { dmClass = distributedDeviceManager.createDeviceManager('com.example.remotephotodemo'); } catch (err) { hilog.error(0x0000, 'testTag', '创建设备管理实例失败: ' + JSON.stringify(err)); }}
// 获取设备B的networkIdfunction getRemoteDeviceId(): string | undefined { initDmClass(); if (!dmClass) return undefined; hilog.info(0x0000, 'testTag', '开始查找远程设备'); const deviceList = dmClass.getAvailableDeviceListSync(); if (!deviceList || deviceList.length === 0) { hilog.info(0x0000, 'testTag', '未找到可用设备'); return undefined; } // 这里取第一个设备,实际开发可做设备选择列表 return deviceList[0].networkId;}
复制代码

3、创建会话并连接(两端操作不同)

设备 A(发起端):创建会话+发起连接

@StorageLink('sessionId') sessionId: number = -1;
// 配置设备B的协同信息const peerInfo: abilityConnectionManager.PeerInfo = { deviceId: getRemoteDeviceId()!, // 设备B的networkId bundleName: 'com.example.remotephotodemo', // 必须和设备B应用一致 moduleName: 'entry', abilityName: 'EntryAbility', serviceName: 'collabTest' // 自定义服务名,两端要一致};
// 连接配置const connectOptions: abilityConnectionManager.ConnectOptions = { needSendData: true, startOptions: abilityConnectionManager.StartOptionParams.START_IN_FOREGROUND, parameters: { "newKey1": "value1" }};
// 发起连接async function connectRemoteAbility() { const context = this.getUIContext().getHostContext(); try { // 创建会话,获取sessionId this.sessionId = abilityConnectionManager.createAbilityConnectionSession( "collabTest", context, peerInfo, connectOptions ); hilog.info(0x0000, 'testTag', `创建会话成功,sessionId: ${this.sessionId}`); // 发起连接(会拉起设备B的应用) const connectResult = await abilityConnectionManager.connect(this.sessionId); if (!connectResult.isConnected) { hilog.info(0x0000, 'testTag', '连接失败'); return; } hilog.info(0x0000, 'testTag', '连接成功'); } catch (error) { hilog.error(0x0000, 'testTag', `连接异常: ${JSON.stringify(error)}`); }}
复制代码

设备 B(接收端):被拉起后接受连接

设备 A 发起连接后,设备 B 的应用会被协同拉起,触发onCollaborate生命周期函数:


export default class EntryAbility extends UIAbility {  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {    hilog.info(0x0000, 'testTag', '应用启动');  }
// 协同拉起时触发 onCollaborate(wantParam: Record<string, Object>): AbilityConstant.CollaborateResult { hilog.info(0x0000, 'testTag', '收到协同请求'); const collabParam = wantParam["ohos.extra.param.key.supportCollaborateIndex"] as Record<string, Object>; this.handleCollaborate(collabParam); return 0; }
// 处理协同连接 private async handleCollaborate(collabParam: Record<string, Object>) { const sessionId = this.createSessionFromParam(collabParam); if (sessionId === -1) { hilog.error(0x0000, 'testTag', '会话创建失败'); return; }
// 获取协同token,必须传入acceptConnect const collabToken = collabParam["ohos.dms.collabToken"] as string; try { await abilityConnectionManager.acceptConnect(sessionId, collabToken); hilog.info(0x0000, 'testTag', '接受连接成功'); AppStorage.setOrCreate('sessionId', sessionId); } catch (error) { hilog.error(0x0000, 'testTag', `接受连接失败: ${JSON.stringify(error)}`); } }
// 从协同参数创建会话 private createSessionFromParam(collabParam: Record<string, Object>): number { let sessionId = -1; const peerInfo = collabParam["PeerInfo"] as abilityConnectionManager.PeerInfo; const connectOptions = collabParam["ConnectOption"] as abilityConnectionManager.ConnectOptions;
if (!peerInfo || !connectOptions) return sessionId;
// 配置数据传输能力 connectOptions.needSendData = true; connectOptions.needSendStream = true;
try { sessionId = abilityConnectionManager.createAbilityConnectionSession( "collabTest", this.context, peerInfo, connectOptions ); } catch (error) { hilog.error(0x0000, 'testTag', `创建会话失败: ${JSON.stringify(error)}`); } return sessionId; }}
复制代码

4、 注册事件监听(两端都要加)

连接成功后,通过监听事件获取连接状态和消息:


function registerEventListeners(sessionId: number) {  // 监听连接成功事件  abilityConnectionManager.on("connect", sessionId, (callbackInfo) => {    hilog.info(0x0000, 'testTag', `会话${callbackInfo.sessionId}连接成功`);  });
// 监听断开连接事件 abilityConnectionManager.on("disconnect", sessionId, (callbackInfo) => { hilog.info(0x0000, 'testTag', `会话${callbackInfo.sessionId}已断开`); });
// 监听接收消息事件 abilityConnectionManager.on("receiveMessage", sessionId, (callbackInfo) => { hilog.info(0x0000, 'testTag', `收到消息: ${callbackInfo.message}, 会话ID: ${callbackInfo.sessionId}`); // 这里可以处理业务逻辑,比如更新UI显示消息 });}
复制代码

5、 发送消息(两端都可发)

连接成功后,用sendMessage发送文本信息:


async function sendTestMessage(sessionId: number) {  try {    await abilityConnectionManager.sendMessage(sessionId, "这是来自设备A的测试消息");    hilog.info(0x0000, 'testTag', '消息发送成功');  } catch (error) {    hilog.error(0x0000, 'testTag', `消息发送失败: ${JSON.stringify(error)}`);  }}
复制代码

6、 结束协同(关键!避免资源泄露)

业务完成后一定要断开连接或销毁会话:


function endCollaboration(sessionId: number) {  if (sessionId === -1) {    hilog.info(0x0000, 'testTag', '无效的会话ID');    return;  }
// 短期还需协同:只断开连接,保留sessionId abilityConnectionManager.disconnect(sessionId); hilog.info(0x0000, 'testTag', '已断开连接');
// 长期不用:销毁会话(自动断开连接) abilityConnectionManager.destroyAbilityConnectionSession(sessionId); hilog.info(0x0000, 'testTag', '已销毁会话');}
复制代码

五、注意事项:

  1. 仅支持 API 18 及以上版本,且设备必须登录相同华为账号

  2. 只有相同 bundleName 的 UIAbility 才能协同(比如都是“com.example.remotephotodemo”)

  3. 协同结束后一定要及时关闭,锁屏或退后台 5 秒未申请长时任务,协同会被系统强制结束

  4. 传输隐私数据时,记得加弹框提醒用户(系统不审查传输内容)

发布于: 刚刚阅读数: 2
用户头像

GeorgeGcs

关注

路漫漫其修远兮,吾将上下而求索。 2024-12-24 加入

鸿蒙创作先锋,华为HDE专家,鸿蒙讲师,作者。 目前任职鸿蒙应用架构师。历经腾讯,宝马,研究所,金融。 待过私企,外企,央企。 深耕大应用开发领域十年。 OpenHarmony,HarmonyOS,Flutter,H5,Android,IOS。

评论

发布
暂无评论
【HarmonyOS 6】UIAbility跨设备连接详解(分布式软总线运用)_GeorgeGcs_InfoQ写作社区