一台设备干不完的活,为什么不让“全家桶”一起上?——鸿蒙分布式能力(Super Device)跨设备协同实战!
大家好,我是[晚风依旧似温柔],新人一枚,欢迎大家关注~
本文目录:
前言
先抛个灵魂拷问:
都 2025 年了,你的 App 还只跑在一台设备上,不觉得有点“保守”吗?
想象一下这些场景:
- 手机上点开视频 → 自动推到电视大屏播放,手机变身遥控器和弹幕输入端
- 平板写文档 → 手机突然响了个消息 → 手机打开就是“同一个文档、同一处光标位置”
- 手表采集运动数据 → 实时同步到手机 → 手机上画曲线、出报告
- 车机播歌 → 手机调音量、切歌 → 回家后电视继续播刚才那首
这些事儿拼接口、靠一堆“蓝牙 + Wi-Fi + 本地同步 + 轮询”也不是不能做,就是——又土又累又不稳。
鸿蒙的 分布式能力(Super Device) 干的事情,简单粗暴一句话:
让多台设备像“一个超级设备”一样工作,
让开发者用“写单机”的心智,做“多端协同”的体验。
这章我们就按你给的那条大纲,一步步把几个关键点掰开讲:
- 分布式软总线到底是什么鬼?
- 设备是怎么自动发现、自动连到一起的?
- 分布式数据对象怎么用一份对象搞定多端同步?
- UI 跨端协同到底是怎么设计出来的,不是喊喊口号?
- 跨屏输入、跨端播放这种骚操作如何落地?
- 安全和权限这一块,哪里最容易踩坑?
别担心,全程有代码、有图景、有吐槽,不整那种 PPT 式废话。
一、分布式软总线:所有跨设备能力的“血管”
先说重点:不理解分布式软总线,后面所有分布式 API 都会是玄学。
1.1 为什么要软总线?
传统做法:
- 手机想跟电视说话:你要么配对蓝牙,要么搞个局域网 IP,再来一层自定义协议
- 再加上车机、手表、平板……每多一台设备,你就多一个“对接方案”
久而久之,你的项目结构就会变成:
“一堆 if (deviceType == xxx) 的 spaghetti code(意大利面代码)”,
维护起来跟拆炸弹差不多。
鸿蒙干脆直接整了个分布式软总线(SoftBus),给它的定位大概是:
在系统层统一管理设备发现、连接、通道、加密、传输,
你在上层只管写“我要发一个对象给某台设备”。
换张嘴说:
- 你不用管设备是通过 Wi-Fi 连接还是蓝牙直连
- 你不用记对面 IP、端口
- 你不用自己做“可靠传输 + 重连”
- 你甚至可以不用自己造消息通道
系统帮你抽象出一个“分布式网络空间”,你只需要:
- 拿到设备列表
- 决定要和谁协同
- 扔数据 / 调用分布式 API
就这。
1.2 SoftBus 在代码里长什么样?
通常我们是通过“设备管理”这条线来获知 SoftBus 已经搭好,然后再玩后面的分布式对象、协同能力。
一个典型入口是 Distributed Device Manager。示例(伪代码,接口名不同版本会有轻微出入,但套路是一样的):
import deviceManager from '@ohos.distributedDeviceManager';
let dm: deviceManager.DeviceManager | null = null;
deviceManager.createDeviceManager('com.example.superdevice', (err, manager) => {
if (err) {
console.error('创建 DeviceManager 失败:', JSON.stringify(err));
return;
}
dm = manager;
console.info('DeviceManager 创建成功');
});
拿到 dm 之后,你就等于站在了整个分布式网络的门口,后面所有“发现设备、连接设备、建立协同”的动作,基本都从这里起步。
后面我们会基于这个继续往下走。
二、设备发现与连接:设备怎么“自动认识彼此”?
你看,SoftBus 在内核层面帮你统一了通道,那上层第一步就得解决:设备怎么互相找到、互相信任?
鸿蒙这块做得比较“人性化”:
- 设备发现:自动发现局域网 / 同账号 / 同可信域下的设备
- 认证连接:用户确认 + 证书交换
- 状态监听:在线 / 离线 / 变化回调
2.1 启动设备发现
const SUBSCRIBE_ID = 1001;
function startDiscover() {
if (!dm) return;
dm.startDeviceDiscovery({
subscribeId: SUBSCRIBE_ID,
mode: 0, // 主动发现
medium: 0, // 由系统自动决定用 Wi-Fi/BT 等
freq: 1, // 发现频率
isSameAccount: true,
isWakeRemote: true
}, (err) => {
if (err) {
console.error('启动设备发现失败:', JSON.stringify(err));
} else {
console.info('设备发现已启动');
}
});
dm.on('deviceFound', (device) => {
console.info('发现设备:', JSON.stringify(device));
// 这里可以弹个 UI,让用户选择要连哪一台
});
dm.on('discoverFail', (info) => {
console.error('设备发现失败事件:', JSON.stringify(info));
});
}
你不需要管理什么搜索广播包、不同链路,只要启动发现,然后等回调,就像等外卖一样。
2.2 设备认证与连接
一旦用户选中一台设备,你通常要走一遍认证流程:
function authDevice(deviceId: string) {
if (!dm) return;
const authParam = {
authType: 1, // 比如 PIN 验证 / 对码等,由系统 UI 帮你做
appIcon: 'xxx',
appName: 'Super Device Demo'
};
dm.authenticateDevice(deviceId, authParam, (err, result) => {
if (err) {
console.error('认证失败:', JSON.stringify(err));
return;
}
console.info('认证成功,token = ' + result.token);
// 后续可以存一份可信设备列表
});
dm.on('deviceOnline', (dev) => {
console.info('设备上线:', JSON.stringify(dev));
});
dm.on('deviceOffline', (dev) => {
console.info('设备下线:', JSON.stringify(dev));
});
}
一旦认证成功,同一账户、同一可信网域内,多数情况下你后续都不用再重复认证,直接用设备 ID 搞协同就行。
三、分布式数据对象:多设备共享“一块内存”的感觉
如果你让我选 HarmonyOS 分布式能力里最有“黑科技感”的一块,我肯定投 Distributed Data Object(分布式数据对象) 一票。
它大概的体验是:
你在手机上
obj.count++,
平板、电视、手表上监听这个对象的页面就会一起刷新。
没有显式“发消息”、“写 socket”、“做同步”,你只是在改一个对象。
3.1 创建一个分布式数据对象
import distributedDataObject from '@ohos.data.distributedDataObject';
// 定义一个跨设备共享的状态
const docState = distributedDataObject.create({
title: '未命名文档',
content: '',
cursor: 0,
lastEditDevice: '',
});
// 监听变化(每个设备都可以监听)
docState.on('change', (changedFields) => {
console.info('分布式对象变化:', JSON.stringify(changedFields));
// 比如刷新 UI、更新光标位置
});
这时候,只要你的设备已经处在同一个分布式网络中并且启用了分布式同步,这个 docState 就像放在“分布式内存”里一样。
3.2 修改数据 = 自动同步
在手机端:
function onUserInput(text: string) {
docState.content = text;
docState.lastEditDevice = 'phone';
}
在平板端:
docState.on('change', () => {
editor.setText(docState.content);
console.info('来自:' + docState.lastEditDevice);
});
你完全没有看到什么网络请求、序列化、信道选择;
你唯一看到的是:
- 改对象
- 自动同步
- 监听变化
这套东西用在:
- 多端文档编辑
- 多设备播放控制状态(当前播放进度 / 播放状态)
- 家庭 IoT 场景下的“当前场景状态”
- 多端白板协同
都非常舒服。
四、跨端 UI 协同设计:不是简单“投屏”,而是“迁移”和“协作”
很多人一听“跨端 UI”,第一反应是 —— 投个屏不就完了?
说实话,这种理解太屈才了。
鸿蒙的思路是:
UI 不是死在一台设备上的,而是可以在设备之间
迁移 / 拆分 / 协同。
4.1 能力 1:界面迁移(Continuation)
最典型的例子:视频从手机迁移到电视。
在手机侧的 UIAbility:
// 允许迁移时携带状态
onContinue(wantParams: Record<string, Object>): boolean {
wantParams['videoUrl'] = this.currentVideoUrl;
wantParams['position'] = this.currentPosition;
wantParams['fromDevice'] = 'phone';
return true; // 同意迁移
}
在电视侧接住:
onCreate(want: any) {
const params = want.parameters ?? {};
const url = params['videoUrl'];
const pos = params['position'] ?? 0;
if (url) {
this.player.setSource(url);
this.player.seek(pos);
this.player.play();
}
}
这一来一回,两边 UI 跑的是同一套业务逻辑,只是界面的承载设备变了:
- 手机变成控制端
- 电视变成主播放端
而不是简单把“画面投出去”那么粗糙。
4.2 能力 2:多屏协作设计思路
这种能力玩起来就很有意思了,比如:
- 平板 显示文档主区域
- 手机 只显示工具栏和评论列表
- 手写板 只负责手写/涂鸦
设计思路一般是:
- 用 分布式数据对象 管“业务状态”
- 用 多 Ability 按设备类型渲染不同 UI
- 用 设备信息(屏幕尺寸、输入能力) 决定显示布局
伪代码示意:
import deviceManager from '@ohos.distributedDeviceManager';
function getDeviceRole(deviceInfo): 'main' | 'tool' | 'input' {
if (deviceInfo.deviceType === 'tablet') return 'main';
if (deviceInfo.deviceType === 'phone') return 'tool';
if (deviceInfo.deviceType === 'stylusBoard') return 'input';
return 'tool';
}
然后在不同端,根据 role 决定渲染哪些组件。
统一的业务状态 + 不同的 UI 布局,这才是真正的“跨端协同”。
五、跨设备调用示例:跨屏输入、跨端播放怎么搞?
光讲理念太虚,我们来点“有手就能 copy 的例子”。
5.1 跨屏输入:手机当电视的输入法
场景:
- 电视上有一个搜索框
- 遥控器打字太折磨人
- 手机同账号登录以后,直接变成电视的“键盘”
5.1.1 电视侧:暴露一个“远程输入”接口
你可以用分布式 RPC / 自定义服务 / 分布式数据对象承载,下面用一个超简化思路:
// 假设我们用分布式对象承载输入内容
const searchInput = distributedDataObject.create({
text: '',
fromDevice: '',
});
searchInput.on('change', () => {
if (searchInput.fromDevice === 'phone') {
tvSearchBox.setText(searchInput.text);
}
});
5.1.2 手机侧:同步用户输入
function onPhoneInputChange(text: string) {
searchInput.text = text;
searchInput.fromDevice = 'phone';
}
如果你想做得更“底层”一点,也可以用分布式输入设备能力(不同版本 SDK 的命名略有区别),核心逻辑是:
- 电视注册一个“接收按键/文本事件”的监听
- 手机作为发送端,发“按键事件 / 文本事件”
5.2 跨端播放:手机控制电视播放
常见玩法:
- 手机选择一个视频 → 选择目标设备 → 让对方播放
- 手机动态控制“播放 / 暂停 / 进度 / 音量”
5.2.1 电视侧:注册一个“媒体控制服务”
伪代码示意:
import serviceExtension from '@ohos.app.ability.ServiceExtensionAbility';
import rpc from '@ohos.rpc';
class TvPlayerRemote extends rpc.RemoteObject {
player: any;
constructor(descriptor: string) {
super(descriptor);
this.player = createTvMediaPlayer();
}
onRemoteRequest(code: number, data: rpc.MessageParcel, reply: rpc.MessageParcel) {
switch (code) {
case 1: // play
const url = data.readString();
this.player.setSource(url);
this.player.play();
return true;
case 2: // pause
this.player.pause();
return true;
case 3: // seek
const pos = data.readInt();
this.player.seek(pos);
return true;
default:
return false;
}
}
}
export default class TvPlayerService extends serviceExtension {
remote: TvPlayerRemote | null = null;
onCreate() {
this.remote = new TvPlayerRemote('TvPlayerRemote');
}
onConnect() {
return this.remote;
}
}
5.2.2 手机侧:作为控制端
class TvPlayerProxy {
constructor(private remote: rpc.IRemoteObject) {}
play(url: string) {
let data = rpc.MessageParcel.create();
let reply = rpc.MessageParcel.create();
let opt = new rpc.MessageOption();
data.writeString(url);
return this.remote.sendRequest(1, data, reply, opt);
}
pause() {
let data = rpc.MessageParcel.create();
let reply = rpc.MessageParcel.create();
let opt = new rpc.MessageOption();
return this.remote.sendRequest(2, data, reply, opt);
}
seek(pos: number) {
let data = rpc.MessageParcel.create();
let reply = rpc.MessageParcel.create();
let opt = new rpc.MessageOption();
data.writeInt(pos);
return this.remote.sendRequest(3, data, reply, opt);
}
}
配合上“设备发现 + 用户选择目标设备 + 权限认证”,就可以做一个完整的“投屏 + 遥控”体验了。
六、安全与权限问题:跨设备不是“裸连”,安全得先想明白
凡是跟“跨设备”“分布式”的东西,安全一定是重中之重。
你总不能随便搞个 App 就能控制别人家的电视、车机、摄像头吧?
6.1 设备层面的安全:可信设备 + 用户确认
鸿蒙分布式设备的安全通常包含几层:
- 同一华为账号 / 同一家庭组 / 同一可信域
- 首次连接需要用户确认(PIN、扫码、弹窗)
- 系统维护设备证书与信任关系
- 后续使用走的是加密通道
也就是说,就算你知道对面设备的 ID,只要不是可信设备,系统也不会让你随意拉通分布式能力。
6.2 应用层面的权限声明
你要玩分布式,就离不开权限,例如:
{
"module": {
"abilities": [ /* ... */ ],
"requestPermissions": [
"ohos.permission.DISTRIBUTED_DATASYNC", // 分布式数据同步
"ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE", // 监听设备状态
"ohos.permission.GET_NETWORK_INFO",
"ohos.permission.INTERNET"
]
}
}
你没声明,跑的时候就会被系统毫不留情地拦下来。
对于跨设备调用某些“敏感能力”(比如摄像头、麦克风、定位),还会涉及到目标设备上的二次授权,这一点在设计 UX 时必须考虑进去:
- 不要“连着连着”突然把对方摄像头打开
- 不要悄悄从别的设备录音、采集位置
6.3 通信层安全:
软总线在通信层帮你做了一堆事情:
- 加密传输
- 会话校验
- 消息完整性
你不需要自己再实现一套复杂的 SSL / TLS,
但你要对“哪些数据可以跨设备传”有最低限度的自觉:
- 不要传明文密码
- 不要在不合规的前提下同步隐私数据
- 尽量对敏感信息做脱敏
在企业项目里,很多安全审计就是卡在这里:
技术做得很酷,合规上完全不合格。
写在最后:分布式不是“加个卖点”,是真正改变架构思维
总结一下今天这趟旅程:
- 分布式软总线:统一传输底座,让你不用再操心蓝牙/Wi-Fi/局域网底层细节
- 设备发现与连接:自动发现 + 用户确认 + 可信域管理,避免设备乱连
- 分布式数据对象:像操作本地对象一样搞多端数据同步
- 跨端 UI 协同:界面可迁移、可拆分、可协作,不是简单投屏
- 跨设备调用(输入/播放等):服务 + RPC + 分布式,让设备之间互相“打工”
- 安全与权限:没有安全和权限控制,一切分布式都是“高危操作”
更现实一点说:
未来几年,“会不会做分布式协同”,
多半会成为区分普通 App 和“新一代表达力 App”的分水岭。
如果你已经在做鸿蒙原生项目,真心建议:
别把分布式能力当成“锦上添花”,它是你架构升级的大杀器。
如果觉得有帮助,别忘了点个赞+关注支持一下~
喜欢记得关注,别让好内容被埋没~
更多推荐
所有评论(0)