鸿蒙分布式能力
What — 是什么
鸿蒙分布式能力是 HarmonyOS 的核心竞争力,通过分布式软总线、分布式数据管理、分布式任务调度等技术,将多个物理设备融合为一个逻辑上的”超级终端”,实现设备间的无缝协同、数据共享和任务迁移。
核心概念:
- 分布式软总线:设备自动发现、认证、组网,构建统一通信基础
- 超级终端:多设备虚拟化为一个逻辑设备,用户无感切换
- 分布式数据管理:跨设备数据自动同步,应用无需关心设备差异
- 分布式文件系统:跨设备文件透明访问
- 分布式任务调度:远程启动 Ability、跨设备任务迁移
- 一次开发多端部署:一套代码适配多种设备形态
分布式架构:
┌──────────────────────────────────────────────────────┐
│ 超级终端(逻辑设备) │
├──────────────┬──────────────┬────────────────────────┤
│ 手机 │ 平板 │ 智慧屏 │
│ (控制中心) │ (显示扩展) │ (大屏展示) │
├──────────────┴──────────────┴────────────────────────┤
│ 分布式软总线 │
│ 设备发现 → 设备认证 → 设备组网 → 数据传输 │
├──────────────────────────────────────────────────────┤
│ 分布式数据管理 │
│ 分布式数据库 │ 分布式文件 │ 数据同步服务 │
├──────────────────────────────────────────────────────┤
│ 分布式任务调度 │
│ 远程启动 Ability │ 应用迁移 │ 跨设备调用 │
└──────────────────────────────────────────────────────┘
Why — 为什么
适用场景:
- 手机+手表运动数据同步
- 手机+智慧屏视频投屏续播
- 手机+平板文档跨设备编辑
- 手机+车机导航无缝切换
- 多设备协同办公
对比其他平台:
| 维度 | 鸿蒙分布式 | Apple 生态 | Android 生态 |
|---|---|---|---|
| 设备发现 | 自动发现组网 | AirDrop/AirPlay | Google Nearby |
| 数据同步 | 系统级自动 | iCloud | 需第三方 |
| 任务迁移 | 原生支持 | Handoff | 无原生 |
| 文件共享 | 透明访问 | iCloud Drive | 需第三方 |
| 开发复杂度 | 低(API内置) | 中 | 高 |
How — 怎么用
1. 设备发现与管理
import { deviceManager } from '@kit.DistributedServiceKit'
// ===== 设备管理器初始化 =====
let dmInstance: deviceManager.DeviceManager
deviceManager.createDeviceManager('com.example.myapp')
.then((dm) => {
dmInstance = dm
// 监听设备发现
dmInstance.on('deviceFound', (data) => {
console.log('Found device: ' + JSON.stringify(data.device))
})
// 监听设备状态变化
dmInstance.on('deviceStateChange', (data) => {
console.log(`Device ${data.deviceId} state: ${data.action}`)
})
})
// ===== 开始发现设备 =====
dmInstance.startDiscovering({
discoverTarget: {
targetType: 1 // 1=手机, 2=平板, 3=智慧屏
}
})
// ===== 停止发现 =====
dmInstance.stopDiscovering()
// ===== 获取可信设备列表 =====
const devices = dmInstance.getTrustedDeviceListSync()
devices.forEach((device) => {
console.log(`${device.deviceName} (${device.deviceId})`)
})
// ===== 设备信息 =====
interface DeviceInfo {
deviceId: string // 设备唯一标识
deviceName: string // 设备名称
deviceType: number // 设备类型
networkId: string // 网络标识
}
2. 分布式数据管理
import { relationalStore } from '@kit.ArkData'
import { distributedKVStore } from '@kit.ArkData'
// ===== 分布式 KV 数据库 =====
const kvManagerConfig: distributedKVStore.KVManagerConfig = {
bundleName: 'com.example.myapp',
context: getContext(this)
}
const kvManager = distributedKVStore.createKVManager(kvManagerConfig)
const kvStoreConfig: distributedKVStore.KVStoreConfig = {
bundleName: 'com.example.myapp',
storeId: 'sync_store'
}
// 创建分布式 KV 数据库(自动跨设备同步)
kvManager.getKVStore(kvStoreConfig)
.then((store) => {
// 写入数据 — 自动同步到其他设备
store.put('user_name', 'Alice')
store.put('score', '100')
// 读取数据
store.get('user_name').then((value) => {
console.log('Value: ' + value) // Alice
})
// 监听数据变更(来自其他设备的同步)
store.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {
data.updateEntries.forEach((entry) => {
console.log(`Key: ${entry.key}, Value: ${entry.value.value}`)
})
})
})
3. 分布式文件系统
import { fileShare, fs } from '@kit.CoreFileKit'
// ===== 跨设备文件访问 =====
// 通过分布式文件路径访问其他设备上的文件
// 格式:/distributed/{deviceId}/path/to/file
// 读取远程设备文件
const remotePath = `/distributed/${remoteDeviceId}/data/storage/el2/distributed/files/myfile.txt`
try {
const content = fs.readTextSync(remotePath)
console.log('Remote file content: ' + content)
} catch (e) {
console.error('Failed to read remote file: ' + e)
}
// 写入文件(自动同步到对端设备)
const localPath = getContext(this).distributedFilesDir + '/share_data.json'
fs.writeTextSync(localPath, JSON.stringify({ name: 'Alice', score: 100 }))
4. 分布式任务调度(远程启动 Ability)
import { AbilityConstant, common, Want } from '@kit.AbilityKit'
// ===== 远程启动 Ability =====
function startRemoteAbility(deviceId: string) {
const want: Want = {
deviceId: deviceId, // 目标设备 ID
bundleName: 'com.example.myapp',
abilityName: 'RemoteAbility',
parameters: {
'action': 'play_video',
'videoUrl': 'https://example.com/video.mp4'
}
}
const context = getContext(this) as common.UIAbilityContext
context.startAbility(want)
.then(() => console.log('Remote ability started'))
.catch((err) => console.error('Failed: ' + JSON.stringify(err)))
}
// ===== 跨设备返回结果 =====
const want: Want = {
deviceId: remoteDeviceId,
bundleName: 'com.example.myapp',
abilityName: 'SelectAbility'
}
context.startAbilityForResult(want)
.then((result) => {
console.log('Result code: ' + result.resultCode)
console.log('Result data: ' + JSON.stringify(result.want?.parameters))
})
5. 应用迁移(Continuation)
import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit'
import { window } from '@kit.ArkUI'
export default class MigrationAbility extends UIAbility {
// 1. 保存迁移数据
onContinue(wantParam: Record<string, Object>): AbilityConstant.OnContinueResult {
wantParam['currentStep'] = this.currentStep
wantParam['score'] = this.score
return AbilityConstant.OnContinueResult.AGREE
}
// 2. 恢复迁移数据(目标设备上)
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
this.currentStep = want.parameters?.currentStep as number
this.score = want.parameters?.score as number
}
}
// 3. 迁移完成回调
onRestoreData(wantParam: Record<string, Object>): void {
console.log('Migration completed')
}
}
// 触发迁移
@Component
struct MigrationPage {
build() {
Column() {
Button('迁移到其他设备')
.onClick(() => {
const context = getContext(this) as common.UIAbilityContext
context.continueAbility('com.example.myapp')
})
}
}
}
6. 一次开发多端部署
// ===== 断点系统 =====
// sm: 0-600vp (手机竖屏)
// md: 600-840vp (平板竖屏/折叠屏)
// lg: 840+vp (平板横屏/PC)
// 使用 Grid 的断点
GridRow({
columns: {
sm: 4, // 手机4列
md: 8, // 平板8列
lg: 12 // PC 12列
},
gutter: { x: 12, y: 12 },
breakpoints: {
reference: BreakpointsReference.WindowSize,
value: ['600vp', '840vp']
}
}) {
ForEach(this.items, (item: Item) => {
Col({ span: { sm: 4, md: 4, lg: 3 } }) { // 不同断点不同列宽
ItemCard({ item: item })
}
})
}
// ===== 多态组件 =====
@Component
struct AdaptiveList {
@State currentBreakpoint: string = 'sm'
build() {
if (this.currentBreakpoint === 'sm') {
// 手机:垂直列表
List() {
ForEach(this.items, (item) => ListItem() { ItemCard({ item }) })
}
} else {
// 平板/PC:网格
Grid() {
ForEach(this.items, (item) => GridItem() { ItemCard({ item }) })
}
.columnsTemplate('1fr 1fr 1fr')
}
}
}
// ===== 设备信息获取 =====
import { deviceInfo, display } from '@kit.BasicServicesKit'
// 设备类型
const deviceType = deviceInfo.deviceType // 'phone'/'tablet'/'tv'/'wearable'/'car'
// 屏幕尺寸
display.getDefaultDisplaySync().let((disp) => {
const width = disp.width // 物理像素宽度
const height = disp.height
const density = disp.densityDPI // DPI
})
7. 折叠屏适配
import { display } from '@kit.BasicServicesKit'
@Component
struct FoldablePage {
@State isFolded: boolean = true
aboutToAppear() {
// 监听折叠状态变化
display.on('foldStatusChange', (status: display.FoldStatus) => {
this.isFolded = status === display.FoldStatus.FOLD_STATUS_FOLDED
})
}
build() {
if (this.isFolded) {
// 折叠态:单列布局
Column() {
ContentArea()
}
} else {
// 展开态:双列布局
Row() {
NavigationArea().width('30%')
ContentArea().width('70%')
}
}
}
}
8. 安全与权限
// ===== 权限管理 =====
// 分布式能力需要以下权限(module.json5 声明)
{
"requestPermissions": [
{ "name": "ohos.permission.DISTRIBUTED_DATASYNC" }, // 分布式数据同步
{ "name": "ohos.permission.DISTRIBUTED_SOFTBUS_CENTER" }, // 分布式软总线
{ "name": "ohos.permission.ACCESS_SERVICE_DM" } // 设备管理
]
}
// 敏感权限需要动态申请
import { abilityAccessCtrl, common } from '@kit.AbilityKit'
async function requestPermission(context: common.UIAbilityContext) {
const atManager = abilityAccessCtrl.createAtManager()
const result = await atManager.requestPermissionsFromUser(context, [
'ohos.permission.DISTRIBUTED_DATASYNC'
])
if (result.authResults[0] === 0) {
console.log('Permission granted')
}
}
// ===== 数据安全分级 =====
// S1: 公开数据(天气、新闻)
// S2: 内部数据(应用配置)
// S3: 敏感数据(联系人、位置)
// S4: 极敏感数据(密码、密钥)
// 跨设备同步时,S3/S4 数据需要设备认证+加密传输
常见问题与踩坑
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 设备发现不到 | 未在同一网络/WiFi | 确保设备同一局域网 |
| 数据同步延迟 | 网络波动 | 增加同步超时和重试 |
| 迁移失败 | 目标设备未安装应用 | 确保两端安装同一应用 |
| 权限被拒 | 未声明分布式权限 | module.json5 添加权限 |
| 文件跨设备不可访问 | 沙箱目录不对 | 使用 distributedFilesDir |
| 折叠屏布局错乱 | 未监听折叠状态 | 监听 foldStatusChange |
最佳实践
- 分布式能力需要在 module.json5 声明对应权限
- 敏感数据同步前检查设备认证状态
- 使用分布式 KV 数据库做轻量级同步,大数据用文件系统
- 应用迁移时保存完整的上下文数据
- 多设备适配使用 GridRow 断点系统
- 折叠屏适配监听 foldStatusChange
- 测试时确保设备在同一网络
面试题
Q1: 鸿蒙的分布式软总线是什么?它解决了什么问题?
分布式软总线是鸿蒙设备间通信的基础设施,负责设备自动发现、安全认证、组网和数据传输。它解决了多设备互联的核心问题:①设备发现——自动扫描局域网内的鸿蒙设备;②安全认证——设备间基于证书的双向认证,确保通信安全;③统一组网——将多个物理设备组成一个逻辑网络;④高效传输——支持 Wi-Fi/蓝牙/网线等多种传输方式自动选择最优路径。开发者无需关心底层通信协议,通过高级 API 即可实现跨设备协同。
Q2: 一次开发多端部署的断点系统是如何工作的?
断点系统根据屏幕宽度将设备分为三个档位:sm(<600vp,手机)、md(600-840vp,平板竖屏)、lg(>840vp,平板横屏/PC)。工作流程:框架实时监测窗口尺寸变化 → 匹配对应断点 → 根据断点应用不同的布局策略。GridRow 组件内置断点支持,通过 columns 配置不同断点的列数(sm:4/md:8/lg:12),Col 组件通过 span 设置不同断点的列宽占比。开发者也可以通过 onAreaChange 手动实现断点逻辑。关键:断点以 vp(密度无关像素)为单位,确保不同 DPI 设备体验一致。
Q3: 应用迁移(Continuation)的完整流程是什么?
迁移流程分三步:①源设备 onContinue — 用户触发迁移时,源 Ability 的 onContinue 回调保存当前状态到 wantParam 字典中,返回 AGREE 表示同意迁移;②目标设备 onCreate — 目标设备的 Ability 被创建,launchReason 为 CONTINUATION,从 want.parameters 中恢复数据;③onRestoreData — 迁移完成后的回调,可做最终的 UI 恢复。关键点:onContinue 必须同步返回(不能做异步操作);保存的数据必须是可序列化的基本类型;迁移过程中如果目标设备应用未安装,框架会自动提示安装。
Q4: 分布式 KV 数据库和本地 KV 数据库有什么区别?
分布式 KV 数据库在本地 KV 数据库基础上增加了自动跨设备同步能力。写入数据后,框架自动将变更推送到同一应用的其他设备实例。区别:①同步方式——分布式 KV 自动同步,本地 KV 不同步;②监听——分布式 KV 可以监听远端数据变更(SUBSCRIBE_TYPE_ALL);③冲突解决——分布式 KV 有自动冲突解决策略(last-write-wins 或自定义);④性能——分布式 KV 有网络开销,本地 KV 无。选择:只在本设备使用的数据用本地 KV;需要跨设备同步的用分布式 KV。
Q5: 折叠屏适配需要注意什么?
核心是监听折叠状态变化并动态切换布局。注意事项:①使用 display.on(‘foldStatusChange’) 监听折叠/展开状态;②折叠态用紧凑的单列布局,展开态用双列或更多列的布局;③屏幕尺寸变化时需要重新计算布局参数;④动画过渡要流畅,用 animateTo 平滑切换;⑤注意 Activity/Ability 重建问题——某些设备折叠可能触发 recreate;⑥图片和文字大小需要适配不同屏幕密度;⑦测试要覆盖折叠/展开/半折叠三种状态。
Q6: 鸿蒙的分布式安全机制是怎样的?
分布式安全分三层:①设备认证——设备间基于 PKI 证书双向认证,确保只有可信设备可以通信;②数据加密——跨设备传输的数据使用端到端加密,密钥不经过云端;③数据分级——按 S1-S4 四级分类,S3/S4 级数据跨设备同步需要用户授权确认。权限控制:分布式操作需要 DISTRIBUTED_DATASYNC 等权限,敏感权限需要用户动态授权。沙箱隔离:每个应用有独立沙箱,跨设备访问文件需要通过分布式文件路径,不能直接访问其他应用的沙箱。
Q7: 如何实现”手机拍照→平板编辑→智慧屏展示”的跨设备流转?
实现方案:①手机拍照——通过相机 API 拍照保存到分布式文件目录(distributedFilesDir),照片自动同步到同账号其他设备;②平板编辑——平板端监听分布式文件变化或通过分布式 KV 数据库获取通知,打开照片进行编辑,编辑结果写回分布式文件;③智慧屏展示——通过远程启动 Ability(startAbility 指定 deviceId),智慧屏端 Ability 接收展示参数并全屏渲染。整个流程利用了分布式文件系统(自动同步文件)、分布式 KV 数据库(通知变更)和分布式任务调度(远程启动)三个能力协同完成。
Q8: 鸿蒙分布式和 Apple 的 Handoff/Universal Control 有什么区别?
核心区别在架构层面:①鸿蒙分布式是操作系统级能力,开发者通过标准 API 直接调用;Apple 的 Handoff/Universal Control 是系统应用级功能,开发者通过特定框架(NSUserActivity)参与,但控制粒度有限。②鸿蒙支持跨设备 Ability 迁移(完整的应用状态迁移),Apple Handoff 只传递活动数据(URL/少量上下文)。③鸿蒙分布式数据库自动同步应用数据,Apple 依赖 iCloud 手动管理。④鸿蒙支持跨设备文件透明访问,Apple 通过 iCloud Drive 间接实现。⑤鸿蒙的分布式软总线自动发现组网,Apple 依赖蓝牙/WiFi 发现但不需要显式组网。总体上鸿蒙分布式更底层、更自动化,Apple 更上层、更封闭。
相关链接: