鸿蒙分布式能力

What — 是什么

鸿蒙分布式能力是 HarmonyOS 的核心竞争力,通过分布式软总线、分布式数据管理、分布式任务调度等技术,将多个物理设备融合为一个逻辑上的”超级终端”,实现设备间的无缝协同、数据共享和任务迁移。

核心概念:

  • 分布式软总线:设备自动发现、认证、组网,构建统一通信基础
  • 超级终端:多设备虚拟化为一个逻辑设备,用户无感切换
  • 分布式数据管理:跨设备数据自动同步,应用无需关心设备差异
  • 分布式文件系统:跨设备文件透明访问
  • 分布式任务调度:远程启动 Ability、跨设备任务迁移
  • 一次开发多端部署:一套代码适配多种设备形态

分布式架构:

┌──────────────────────────────────────────────────────┐
│                    超级终端(逻辑设备)                  │
├──────────────┬──────────────┬────────────────────────┤
│   手机       │   平板        │   智慧屏               │
│  (控制中心)   │  (显示扩展)   │  (大屏展示)            │
├──────────────┴──────────────┴────────────────────────┤
│                  分布式软总线                           │
│    设备发现 → 设备认证 → 设备组网 → 数据传输            │
├──────────────────────────────────────────────────────┤
│              分布式数据管理                             │
│   分布式数据库 │ 分布式文件 │ 数据同步服务              │
├──────────────────────────────────────────────────────┤
│              分布式任务调度                             │
│   远程启动 Ability │ 应用迁移 │ 跨设备调用             │
└──────────────────────────────────────────────────────┘

Why — 为什么

适用场景:

  • 手机+手表运动数据同步
  • 手机+智慧屏视频投屏续播
  • 手机+平板文档跨设备编辑
  • 手机+车机导航无缝切换
  • 多设备协同办公

对比其他平台:

维度鸿蒙分布式Apple 生态Android 生态
设备发现自动发现组网AirDrop/AirPlayGoogle 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 更上层、更封闭。


相关链接: