6  第5章 分布式能力

HarmonyOS应用开发者高级认证教程

7 第5章 分布式能力

7.1 学习目标

本章将深入讲解HarmonyOS分布式技术的核心原理与开发实践,涵盖分布式软总线、设备虚拟化、跨设备迁移、分布式任务调度、分布式通信以及分布式协同场景。通过本章学习,读者将能够:

  • 理解分布式软总线的架构原理与设备发现机制
  • 掌握分布式设备虚拟化与超级终端的开发方法
  • 实现跨设备迁移(Continuation)的完整流程
  • 运用分布式任务调度实现跨设备Ability启动
  • 掌握分布式数据对象与跨设备通信的开发技术
  • 理解并实现典型分布式协同应用场景

7.2 5.1 分布式软总线

7.2.1 5.1.1 软总线架构与原理

HarmonyOS分布式软总线(Distributed Soft Bus)是HarmonyOS的核心底座之一,它屏蔽了底层物理通信协议的差异,为上层应用提供统一的分布式通信能力。软总线的核心设计理念是”设备即资源”,将多个物理设备虚拟化为一个逻辑资源池。

软总线架构分层:

┌─────────────────────────────────────────┐
│          分布式应用层                      │
│  (跨设备迁移/协同/数据同步)               │
├─────────────────────────────────────────┤
│          分布式能力层                      │
│  (设备管理/任务调度/数据管理)               │
├─────────────────────────────────────────┤
│          分布式软总线                      │
│  ┌─────────┬──────────┬──────────┐      │
│  │ 设备发现 │ 设备认证  │ 连接管理  │      │
│  └─────────┴──────────┴──────────┘      │
│  ┌─────────┬──────────┬──────────┐      │
│  │ 消息通信 │ 数据传输  │ QoS保障  │      │
│  └─────────┴──────────┴──────────┘      │
├─────────────────────────────────────────┤
│          传输适配层                        │
│  (WiFi/BLE/USB/以太网)                   │
└─────────────────────────────────────────┘

软总线的核心能力包括:

  1. 设备发现:基于组播DNS、BLE广播等多种发现方式
  2. 设备认证:基于PKI体系的安全认证机制
  3. 连接管理:自动选择最优通信链路
  4. 消息通信:提供可靠的消息传递服务
  5. QoS保障:根据业务需求提供不同等级的服务质量

7.2.2 5.1.2 设备发现机制

HarmonyOS提供了 deviceManager 模块用于设备发现。开发者需要配置相应权限并实现设备发现回调。

权限配置(module.json5):

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC",
        "reason": "$string:distributed_sync_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO",
        "reason": "$string:get_device_info_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      }
    ]
  }
}

设备发现代码实现:

import { deviceManager } from '@kit.DistributedServiceKit'
import { common } from '@kit.AbilityKit'

// 设备信息模型
interface DiscoveredDevice {
  deviceId: string
  deviceName: string
  deviceType: string
  isOnline: boolean
}

@Component
struct DeviceDiscoveryDemo {
  @State discoveredDevices: DiscoveredDevice[] = []
  @State isDiscovering: boolean = false
  @State statusText: string = '点击开始发现设备'
  private dmInstance: deviceManager.DeviceManager | null = null

  aboutToAppear(): void {
    this.initDeviceManager()
  }

  aboutToDisappear(): void {
    this.stopDiscovery()
  }

  private initDeviceManager(): void {
    try {
      // 创建DeviceManager实例
      this.dmInstance = deviceManager.createDeviceManager(
        'com.example.distributedapp'
      )

      // 注册设备状态变更回调
      this.dmInstance.on('deviceStateChange', (data: deviceManager.DeviceData): void => {
        const device: DiscoveredDevice = {
          deviceId: data.device.deviceId,
          deviceName: data.device.deviceName ?? '未知设备',
          deviceType: this.getDeviceTypeName(data.device.deviceType),
          isOnline: data.deviceState === 0 // 0=在线
        }

        if (data.deviceState === 0) {
          // 设备上线
          this.addOrUpdateDevice(device)
        } else if (data.deviceState === 1) {
          // 设备离线
          this.removeDevice(device.deviceId)
        }
      })

      // 注册发现失败回调
      this.dmInstance.on('discoverFail', (data: deviceManager.SubscribeInfo,
          errorCode: number): void => {
        console.error(`设备发现失败, 错误码: ${errorCode}`)
        this.statusText = `发现失败: ${errorCode}`
      })

    } catch (error) {
      console.error(`创建DeviceManager失败: ${JSON.stringify(error)}`)
    }
  }

  private startDiscovery(): void {
    if (!this.dmInstance || this.isDiscovering) return

    try {
      // 配置订阅信息
      const subscribeInfo: deviceManager.SubscribeInfo = {
        subscribeAllDevice: true,       // 发现所有设备
        discoveryMode: deviceManager.DiscoverMode.DISCOVER_MODE_ACTIVE,
        refreshInterval: 3000           // 刷新间隔(毫秒)
      }

      this.dmInstance.startDiscovering(subscribeInfo)
      this.isDiscovering = true
      this.statusText = '正在发现设备...'
    } catch (error) {
      console.error(`启动设备发现失败: ${JSON.stringify(error)}`)
      this.statusText = '启动发现失败'
    }
  }

  private stopDiscovery(): void {
    if (!this.dmInstance || !this.isDiscovering) return

    try {
      this.dmInstance.stopDiscovering()
      this.isDiscovering = false
      this.statusText = '已停止发现'
    } catch (error) {
      console.error(`停止设备发现失败: ${JSON.stringify(error)}`)
    }
  }

  private addOrUpdateDevice(device: DiscoveredDevice): void {
    const existingIndex = this.discoveredDevices.findIndex(
      (d: DiscoveredDevice) => d.deviceId === device.deviceId
    )
    if (existingIndex >= 0) {
      const updated = [...this.discoveredDevices]
      updated[existingIndex] = device
      this.discoveredDevices = updated
    } else {
      this.discoveredDevices = [...this.discoveredDevices, device]
    }
    this.statusText = `已发现 ${this.discoveredDevices.length} 个设备`
  }

  private removeDevice(deviceId: string): void {
    this.discoveredDevices = this.discoveredDevices.filter(
      (d: DiscoveredDevice) => d.deviceId !== deviceId
    )
  }

  private getDeviceTypeName(type: number): string {
    const typeMap: Record<number, string> = {
      0x00: '未知',
      0x0E: '智能手机',
      0x0C: '平板电脑',
      0x01: '智能电视',
      0x02: '智能穿戴',
      0x03: '智能音箱',
      0x06: '智能手表'
    }
    return typeMap[type] ?? '其他设备'
  }

  build() {
    Column({ space: 16 }) {
      Text('分布式设备发现')
        .fontSize(22)
        .fontWeight(FontWeight.Bold)

      Text(this.statusText)
        .fontSize(14)
        .fontColor(Color.Gray)

      Button(this.isDiscovering ? '停止发现' : '开始发现')
        .onClick(() => {
          if (this.isDiscovering) {
            this.stopDiscovery()
          } else {
            this.startDiscovery()
          }
        })

      // 设备列表
      List() {
        ForEach(this.discoveredDevices, (device: DiscoveredDevice) => {
          ListItem() {
            Row({ space: 12 }) {
              // 设备类型图标
              Column() {
                Text(this.getDeviceIcon(device.deviceType))
                  .fontSize(28)
              }
              .width(50)
              .height(50)
              .borderRadius(25)
              .backgroundColor('#E3F2FD')
              .justifyContent(FlexAlign.Center)

              // 设备信息
              Column({ space: 4 }) {
                Text(device.deviceName)
                  .fontSize(16)
                  .fontWeight(FontWeight.Medium)
                Text(`类型: ${device.deviceType}`)
                  .fontSize(13)
                  .fontColor('#666666')
                Text(`ID: ${device.deviceId.substring(0, 8)}...`)
                  .fontSize(12)
                  .fontColor('#999999')
              }
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1)

              // 在线状态
              Circle()
                .width(12)
                .height(12)
                .fill(device.isOnline ? '#4CAF50' : '#9E9E9E')
            }
            .width('100%')
            .padding(12)
            .backgroundColor(Color.White)
            .borderRadius(12)
          }
        }, (device: DiscoveredDevice) => device.deviceId)
      }
      .width('100%')
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .padding(16)
  }

  private getDeviceIcon(type: string): string {
    return '📱'
  }
}

7.2.3 5.1.3 设备认证与安全

分布式软总线采用基于PKI(公钥基础设施)的设备认证机制,确保跨设备通信的安全性。认证过程包括:

  1. 设备注册:设备首次接入时注册身份信息
  2. 身份认证:基于数字证书的双向身份验证
  3. 密钥协商:通过ECDH等算法协商会话密钥
  4. 加密通信:使用AES等对称加密算法保护数据传输
import { deviceManager } from '@kit.DistributedServiceKit'

// 设备认证管理器
class DeviceAuthManager {
  private dmInstance: deviceManager.DeviceManager | null = null

  constructor(bundleName: string) {
    this.dmInstance = deviceManager.createDeviceManager(bundleName)
  }

  // 发起设备认证
  async authenticateDevice(deviceId: string,
      authType: deviceManager.AuthType): Promise<boolean> {
    return new Promise((resolve, reject) => {
      if (!this.dmInstance) {
        reject(new Error('DeviceManager未初始化'))
        return
      }

      // 监听认证结果
      this.dmInstance!.on('authResult', (data: deviceManager.AuthResult): void => {
        if (data.deviceId === deviceId) {
          if (data.result === 0) {
            console.info(`设备 ${deviceId} 认证成功`)
            resolve(true)
          } else {
            console.error(`设备 ${deviceId} 认证失败: ${data.result}`)
            resolve(false)
          }
        }
      })

      // 发起认证请求
      try {
        this.dmInstance!.authenticateDevice({
          deviceId: deviceId,
          authType: authType
        })
      } catch (error) {
        console.error(`认证请求失败: ${JSON.stringify(error)}`)
        reject(error)
      }
    })
  }

  // 获取已信任设备列表
  getTrustedDevices(): deviceManager.DeviceBasicInfo[] {
    if (!this.dmInstance) return []
    return this.dmInstance.getTrustedDeviceList()
  }

  // 取消信任设备
  unTrustDevice(deviceId: string): void {
    if (!this.dmInstance) return
    this.dmInstance.unDeviceId(deviceId)
  }
}

7.2.4 5.1.4 通信协议选择

HarmonyOS分布式软总线支持多种通信协议,开发者需要根据业务场景选择合适的协议:

协议类型 特点 适用场景
RPC(远程过程调用) 可靠、有序、面向连接 跨设备服务调用
UDP 低延迟、不可靠 实时音视频传输
TCP 可靠、流式传输 文件传输、数据同步

7.3 5.2 分布式设备虚拟化

7.3.1 5.2.1 超级终端概念

超级终端(Super Terminal)是HarmonyOS分布式技术的核心理念,它将多个物理设备的硬件能力虚拟化为一个统一的逻辑设备。用户可以在超级终端中自由选择和组合不同设备的能力,实现跨设备的无缝协同。

超级终端的核心特征:

  • 硬件能力虚拟化:将各设备的摄像头、屏幕、麦克风等硬件能力抽象为统一资源
  • 动态组合:用户可以按需组合不同设备的能力
  • 无缝切换:任务可以在设备间平滑迁移
  • 统一体验:无论使用哪个设备,都获得一致的用户体验

7.3.2 5.2.2 设备能力声明与查询

module.json5 中声明应用所需的设备能力:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "分布式入口Ability",
        "metadata": [
          {
            "name": "ohos.distributedevice.capability",
            "value": "distributedCapability"
          }
        ]
      }
    ],
    "requestPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC"
      },
      {
        "name": "ohos.permission.GET_NETWORK_INFO"
      }
    ]
  }
}

查询设备能力:

import { deviceManager } from '@kit.DistributedServiceKit'

// 设备能力查询工具类
class DeviceCapabilityQuery {
  private dmInstance: deviceManager.DeviceManager

  constructor(bundleName: string) {
    this.dmInstance = deviceManager.createDeviceManager(bundleName)
  }

  // 获取可用设备及其能力
  getAvailableDevicesWithCapabilities(): DeviceCapability[] {
    const devices = this.dmInstance.getAvailableDeviceList()
    const result: DeviceCapability[] = []

    for (const device of devices) {
      const capability: DeviceCapability = {
        deviceId: device.deviceId,
        deviceName: device.deviceName ?? '未知',
        deviceType: device.deviceType,
        hasScreen: this.checkCapability(device, 'screen'),
        hasCamera: this.checkCapability(device, 'camera'),
        hasSpeaker: this.checkCapability(device, 'speaker'),
        hasMicrophone: this.checkCapability(device, 'microphone'),
        hasGPS: this.checkCapability(device, 'gps')
      }
      result.push(capability)
    }

    return result
  }

  private checkCapability(device: deviceManager.DeviceBasicInfo,
      capability: string): boolean {
    // 检查设备是否具备特定能力
    // 实际实现中需要查询设备能力描述符
    return true
  }
}

interface DeviceCapability {
  deviceId: string
  deviceName: string
  deviceType: number
  hasScreen: boolean
  hasCamera: boolean
  hasSpeaker: boolean
  hasMicrophone: boolean
  hasGPS: boolean
}

7.3.3 5.2.3 跨设备任务调度

import { Want } from '@kit.AbilityKit'
import { distributedDeviceManager } from '@kit.DistributedServiceKit'

// 跨设备启动Ability
@Component
struct CrossDeviceLaunchDemo {
  @State targetDeviceId: string = ''
  @State launchResult: string = ''

  build() {
    Column({ space: 16 }) {
      Text('跨设备任务调度')
        .fontSize(22)
        .fontWeight(FontWeight.Bold)

      TextInput({ text: this.targetDeviceId, placeholder: '输入目标设备ID' })
        .onChange((value: string) => {
          this.targetDeviceId = value
        })

      Button('跨设备启动Ability')
        .onClick(() => {
          this.launchRemoteAbility()
        })

      Text(this.launchResult)
        .fontSize(14)
        .fontColor(Color.Gray)
    }
    .width('100%')
    .padding(16)
  }

  private async launchRemoteAbility(): Promise<void> {
    // 构建跨设备Want
    const want: Want = {
      deviceId: this.targetDeviceId,
      bundleName: 'com.example.remoteapp',
      abilityName: 'RemoteAbility',
      parameters: {
        'sourceDevice': 'local_device_id',
        'taskType': 'data_processing',
        'priority': 'high'
      }
    }

    try {
      // 通过context启动远程Ability
      // 实际使用中需要通过getContext获取context
      this.launchResult = '正在启动远程Ability...'
      // context.startAbility(want)
      this.launchResult = '远程Ability启动请求已发送'
    } catch (error) {
      this.launchResult = `启动失败: ${JSON.stringify(error)}`
    }
  }
}

7.3.4 5.2.4 分布式设备管理

import { distributedDeviceManager } from '@kit.DistributedServiceKit'

// 分布式设备管理器
class DistributedDeviceManager {
  private ddm: distributedDeviceManager.DeviceManager | null = null

  async initialize(): Promise<void> {
    try {
      this.ddm = await distributedDeviceManager.createDeviceManager(
        'com.example.distributedapp'
      )
    } catch (error) {
      console.error(`初始化分布式设备管理器失败: ${JSON.stringify(error)}`)
    }
  }

  // 获取组网设备列表
  getGroupedDevices(): DistributedDeviceInfo[] {
    if (!this.ddm) return []

    const devices = this.ddm.getAvailableDeviceListSync()
    return devices.map((device): DistributedDeviceInfo => ({
      deviceId: device.deviceId,
      deviceName: device.deviceName ?? '未知',
      deviceType: device.deviceType ?? 0,
      networkId: device.networkId ?? ''
    }))
  }

  // 获取本地设备信息
  getLocalDeviceInfo(): DistributedDeviceInfo | null {
    if (!this.ddm) return null
    const localDevice = this.ddm.getLocalDeviceInfo()
    return {
      deviceId: localDevice.deviceId,
      deviceName: localDevice.deviceName ?? '本地设备',
      deviceType: localDevice.deviceType ?? 0,
      networkId: localDevice.networkId ?? ''
    }
  }

  destroy(): void {
    this.ddm?.release()
    this.ddm = null
  }
}

interface DistributedDeviceInfo {
  deviceId: string
  deviceName: string
  deviceType: number
  networkId: string
}

7.4 5.3 跨设备迁移(Continuation)

7.4.1 5.3.1 迁移流程与生命周期

跨设备迁移(Continuation)是HarmonyOS的核心分布式特性之一,允许用户将应用从一个设备无缝迁移到另一个设备,保持任务连续性。

迁移流程:

源设备                    目标设备
  │                         │
  │  1. 发起迁移请求         │
  │  (onSaveData)           │
  │ ─────────────────────>  │
  │                         │
  │  2. 传输迁移数据          │
  │ ─────────────────────>  │
  │                         │
  │  3. 目标设备恢复          │
  │     (onRestoreData)     │
  │                         │
  │  4. 源设备清理           │
  │  (onDestroy)            │
  │                         │

迁移生命周期回调:

  • onSaveData(remoteData: Object):源设备保存迁移数据
  • onRestoreData(remoteData: Object):目标设备恢复迁移数据
  • onContinue():目标设备确认迁移完成

7.4.2 5.3.2 迁移权限配置

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.MIGRATE_ABILITY",
        "reason": "$string:migrate_reason",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      },
      {
        "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
      },
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC"
      }
    ],
    "abilities": [
      {
        "name": "EntryAbility",
        "continueAbility": true,
        "srcEntry": "./ets/entryability/EntryAbility.ets"
      }
    ]
  }
}

7.4.3 5.3.3 数据迁移与状态恢复

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'
import { window } from '@kit.ArkUI'
import { distributedDeviceManager } from '@kit.DistributedServiceKit'

// 迁移数据模型
interface MigrationData {
  // 播放状态
  videoUrl: string
  currentPosition: number
  isPlaying: boolean
  volume: number
  // 用户偏好
  subtitleEnabled: boolean
  playbackSpeed: number
  // 业务数据
  videoTitle: string
  watchHistory: WatchRecord[]
}

interface WatchRecord {
  videoId: string
  position: number
  timestamp: number
}

// 支持迁移的UIAbility
export default class MigratableAbility extends UIAbility {
  private migrationData: MigrationData = {
    videoUrl: '',
    currentPosition: 0,
    isPlaying: false,
    volume: 50,
    subtitleEnabled: true,
    playbackSpeed: 1.0,
    videoTitle: '',
    watchHistory: []
  }

  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    console.info('MigratableAbility onCreate')

    // 检查是否从迁移中恢复
    if (want.parameters?.continuationData) {
      const restoredData = want.parameters.continuationData as MigrationData
      this.migrationData = restoredData
      console.info(`从迁移恢复数据: 播放位置 ${restoredData.currentPosition}`)
    }
  }

  // 迁移 - 保存数据
  onSaveData(state: AbilityConstant.AbilityState,
      want: Want): void {
    console.info('onSaveData: 开始保存迁移数据')

    // 获取当前播放状态
    this.migrationData.currentPosition = this.getCurrentPlayPosition()
    this.migrationData.isPlaying = this.getIsPlaying()
    this.migrationData.volume = this.getCurrentVolume()

    // 将数据写入want
    want.parameters = {
      ...want.parameters,
      continuationData: JSON.stringify(this.migrationData)
    }

    console.info(`已保存迁移数据, 位置: ${this.migrationData.currentPosition}`)
  }

  // 迁移 - 恢复数据
  onRestoreData(state: AbilityConstant.AbilityState,
      want: Want): void {
    console.info('onRestoreData: 开始恢复迁移数据')

    if (want.parameters?.continuationData) {
      const data = JSON.parse(want.parameters.continuationData as string)
        as MigrationData
      this.migrationData = data

      // 恢复播放状态
      this.restorePlayback(data)
    }
  }

  // 迁移完成回调
  onContinue(abilityContinueResult: AbilityConstant.ContinueResult): void {
    if (abilityContinueResult === AbilityConstant.ContinueResult.MIGRATION_SUCCESS) {
      console.info('迁移成功')
    } else {
      console.error(`迁移失败: ${abilityContinueResult}`)
    }
  }

  // 辅助方法
  private getCurrentPlayPosition(): number {
    return this.migrationData.currentPosition
  }

  private getIsPlaying(): boolean {
    return this.migrationData.isPlaying
  }

  private getCurrentVolume(): number {
    return this.migrationData.volume
  }

  private restorePlayback(data: MigrationData): void {
    console.info(`恢复播放: ${data.videoTitle} 位置: ${data.currentPosition}`)
  }
}

7.4.4 5.3.4 迁移错误处理

// 迁移错误处理工具类
class ContinuationErrorHandler {
  // 错误码定义
  static readonly ERR_DEVICE_NOT_FOUND = 1003100001
  static readonly ERR_AUTH_FAILED = 1003100002
  static readonly ERR_NETWORK_UNAVAILABLE = 1003100003
  static readonly ERR_DATA_TOO_LARGE = 1003100004
  static readonly ERR_MIGRATION_CANCELLED = 1003100005
  static readonly ERR_ABILITY_NOT_FOUND = 1003100006

  static handleMigrationError(errorCode: number,
      deviceId: string): string {
    switch (errorCode) {
      case ContinuationErrorHandler.ERR_DEVICE_NOT_FOUND:
        return `目标设备未找到,请确认设备在线: ${deviceId}`

      case ContinuationErrorHandler.ERR_AUTH_FAILED:
        return '设备认证失败,请重新进行设备配对'

      case ContinuationErrorHandler.ERR_NETWORK_UNAVAILABLE:
        return '网络连接不可用,请检查网络设置'

      case ContinuationErrorHandler.ERR_DATA_TOO_LARGE:
        return '迁移数据过大,请减少需要同步的数据量'

      case ContinuationErrorHandler.ERR_MIGRATION_CANCELLED:
        return '迁移已被用户取消'

      case ContinuationErrorHandler.ERR_ABILITY_NOT_FOUND:
        return '目标设备未安装兼容的应用'

      default:
        return `未知迁移错误: ${errorCode}`
    }
  }

  // 迁移前检查
  static async preMigrationCheck(deviceId: string):
      Promise<{ success: boolean, message: string }> {
    // 检查网络状态
    const hasNetwork = await ContinuationErrorHandler.checkNetwork()
    if (!hasNetwork) {
      return {
        success: false,
        message: '网络连接不可用,无法执行迁移'
      }
    }

    // 检查目标设备是否在线
    const isOnline = await ContinuationErrorHandler
      .checkDeviceOnline(deviceId)
    if (!isOnline) {
      return {
        success: false,
        message: '目标设备离线,请确认设备已开机且在同一网络'
      }
    }

    return {
      success: true,
      message: '迁移前检查通过'
    }
  }

  private static async checkNetwork(): Promise<boolean> {
    // 实际实现中检查网络连接状态
    return true
  }

  private static async checkDeviceOnline(
      deviceId: string): Promise<boolean> {
    // 实际实现中检查设备在线状态
    return true
  }
}

7.4.5 5.3.5 视频播放跨设备迁移完整示例

import { UIAbility, AbilityConstant, Want } from '@kit.AbilityKit'
import { common } from '@kit.AbilityKit'

// 视频播放迁移 - 完整的UI组件
@Entry
@Component
struct VideoMigrationPage {
  @State videoUrl: string = 'https://example.com/video.mp4'
  @State videoTitle: string = 'HarmonyOS分布式演示'
  @State currentPosition: number = 0
  @State duration: number = 3600
  @State isPlaying: boolean = false
  @State volume: number = 80
  @State availableDevices: DeviceInfo[] = []
  @State migratingTo: string = ''
  private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext

  build() {
    Column({ space: 16 }) {
      // 视频播放区域
      Stack() {
        // 视频播放器(示意)
        Column() {
          Text(this.videoTitle)
            .fontSize(20)
            .fontColor(Color.White)
          Text(`播放进度: ${this.formatTime(this.currentPosition)} / ${this.formatTime(this.duration)}`)
            .fontSize(14)
            .fontColor(Color.White)
        }
        .width('100%')
        .height(220)
        .backgroundColor('#1A1A1A')
        .justifyContent(FlexAlign.Center)
        .borderRadius(12)

        // 播放/暂停按钮
        Button(this.isPlaying ? '⏸' : '▶')
          .fontSize(24)
          .type(ButtonType.Circle)
          .width(56)
          .height(56)
          .onClick(() => {
            this.isPlaying = !this.isPlaying
          })
      }
      .width('100%')

      // 进度条
      Slider({
        value: this.currentPosition,
        min: 0,
        max: this.duration,
        step: 1
      })
        .onChange((value: number) => {
          this.currentPosition = value
        })

      // 音量控制
      Row({ space: 12 }) {
        Text('音量')
          .fontSize(14)
        Slider({
          value: this.volume,
          min: 0,
          max: 100,
          step: 1
        })
          .layoutWeight(1)
          .onChange((value: number) => {
            this.volume = value
          })
      }
      .width('100%')

      Divider()

      // 迁移控制区域
      Text('跨设备迁移')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .width('100%')

      // 可用设备列表
      if (this.availableDevices.length === 0) {
        Text('正在搜索可用设备...')
          .fontSize(14)
          .fontColor(Color.Gray)
      } else {
        ForEach(this.availableDevices, (device: DeviceInfo) => {
          Row({ space: 12 }) {
            Column() {
              Text(device.deviceName)
                .fontSize(16)
              Text(device.deviceType)
                .fontSize(12)
                .fontColor('#999999')
            }
            .alignItems(HorizontalAlign.Start)
            .layoutWeight(1)

            Button('迁移')
              .type(ButtonType.Capsule)
              .height(36)
              .enabled(this.migratingTo !== device.deviceId)
              .onClick(() => {
                this.startMigration(device.deviceId)
              })
          }
          .width('100%')
          .padding(12)
          .backgroundColor('#F5F5F5')
          .borderRadius(8)
        }, (device: DeviceInfo) => device.deviceId)
      }

      // 迁移状态
      if (this.migratingTo) {
        Row({ space: 8 }) {
          LoadingProgress()
            .width(24)
            .height(24)
          Text(`正在迁移到设备...`)
            .fontSize(14)
            .fontColor('#FF9800')
        }
        .width('100%')
        .padding(12)
        .backgroundColor('#FFF3E0')
        .borderRadius(8)
      }
    }
    .width('100%')
    .padding(16)
  }

  private async startMigration(targetDeviceId: string): Promise<void> {
    // 迁移前检查
    const checkResult = await ContinuationErrorHandler
      .preMigrationCheck(targetDeviceId)
    if (!checkResult.success) {
      console.error(`迁移检查失败: ${checkResult.message}`)
      return
    }

    this.migratingTo = targetDeviceId

    try {
      // 发起迁移
      await this.context.continueAbility(targetDeviceId)
      console.info('迁移请求已发送')
    } catch (error) {
      const errorCode = (error as BusinessError).code ?? -1
      const errorMsg = ContinuationErrorHandler
        .handleMigrationError(errorCode, targetDeviceId)
      console.error(`迁移失败: ${errorMsg}`)
      this.migratingTo = ''
    }
  }

  private formatTime(seconds: number): string {
    const min = Math.floor(seconds / 60)
    const sec = Math.floor(seconds % 60)
    return `${min.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`
  }
}

class DeviceInfo {
  deviceId: string
  deviceName: string
  deviceType: string

  constructor(deviceId: string, deviceName: string, deviceType: string) {
    this.deviceId = deviceId
    this.deviceName = deviceName
    this.deviceType = deviceType
  }
}

class BusinessError extends Error {
  code: number
  constructor(code: number, message: string) {
    super(message)
    this.code = code
  }
}

7.5 5.4 分布式任务调度

7.5.1 5.4.1 跨设备Ability启动

import { Want } from '@kit.AbilityKit'
import { common } from '@kit.AbilityKit'

// 跨设备Ability启动管理器
class CrossDeviceAbilityLauncher {
  private context: common.UIAbilityContext

  constructor(context: common.UIAbilityContext) {
    this.context = context
  }

  // 启动远程设备的Ability
  async launchRemoteAbility(options: LaunchOptions): Promise<void> {
    const want: Want = {
      deviceId: options.targetDeviceId,
      bundleName: options.bundleName,
      abilityName: options.abilityName,
      uri: options.uri,
      parameters: {
        ...options.parameters,
        'ohos.distribution.sourceDevice': this.getLocalDeviceId()
      }
    }

    try {
      await this.context.startAbility(want)
      console.info(`成功启动远程Ability: ${options.abilityName}`)
    } catch (error) {
      console.error(`启动远程Ability失败: ${JSON.stringify(error)}`)
      throw error
    }
  }

  // 启动远程设备的ServiceAbility
  async connectRemoteService(options: LaunchOptions):
      Promise<number> {
    const want: Want = {
      deviceId: options.targetDeviceId,
      bundleName: options.bundleName,
      abilityName: options.abilityName,
      parameters: options.parameters
    }

    return new Promise((resolve, reject) => {
      const connectionId = this.context.connectAbilityWithAccount(want, {
        onConnect: (elementName: string, serviceAbilityId: number) => {
          console.info(`远程服务已连接: ${elementName}`)
          resolve(serviceAbilityId)
        },
        onDisconnect: (elementName: string, serviceAbilityId: number) => {
          console.info(`远程服务已断开: ${elementName}`)
        },
        onFailed: (errorCode: number) => {
          console.error(`连接远程服务失败: ${errorCode}`)
          reject(new Error(`连接失败: ${errorCode}`))
        }
      })
    })
  }

  private getLocalDeviceId(): string {
    // 获取本地设备ID
    return 'local_device'
  }
}

interface LaunchOptions {
  targetDeviceId: string
  bundleName: string
  abilityName: string
  uri?: string
  parameters?: Record<string, Object>
}

7.5.2 5.4.2 分布式任务同步

// 分布式任务管理器
class DistributedTaskManager {
  private taskQueue: DistributedTask[] = []
  private taskCallbacks: Map<string, TaskCallback> = new Map()

  // 提交任务到分布式环境
  async submitTask(task: DistributedTask): Promise<string> {
    // 根据任务优先级和设备负载选择执行设备
    const targetDevice = await this.selectOptimalDevice(task)

    if (targetDevice === 'local') {
      // 本地执行
      return this.executeLocally(task)
    } else {
      // 远程执行
      return this.executeRemotely(task, targetDevice)
    }
  }

  // 选择最优执行设备
  private async selectOptimalDevice(
      task: DistributedTask): Promise<string> {
    // 考虑因素:
    // 1. 任务优先级
    // 2. 设备负载
    // 3. 网络延迟
    // 4. 设备能力匹配度
    // 5. 电池电量

    const candidates = this.getAvailableDevices()
    let bestDevice = 'local'
    let bestScore = this.scoreDevice('local', task)

    for (const device of candidates) {
      const score = this.scoreDevice(device.deviceId, task)
      if (score > bestScore) {
        bestScore = score
        bestDevice = device.deviceId
      }
    }

    return bestDevice
  }

  private scoreDevice(deviceId: string,
      task: DistributedTask): number {
    let score = 0
    // 简化评分逻辑
    if (deviceId === 'local') {
      score += 10 // 本地执行基础分
    }
    // 根据任务类型和设备能力加分
    if (task.requiresGPU && this.deviceHasGPU(deviceId)) {
      score += 20
    }
    if (task.requiresHighMemory && this.deviceHasHighMemory(deviceId)) {
      score += 15
    }
    return score
  }

  private getAvailableDevices(): DeviceInfo[] {
    return []
  }

  private deviceHasGPU(deviceId: string): boolean {
    return true
  }

  private deviceHasHighMemory(deviceId: string): boolean {
    return true
  }

  private async executeLocally(
      task: DistributedTask): Promise<string> {
    const taskId = `local_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`
    this.taskQueue.push({ ...task, taskId, status: 'running' })
    return taskId
  }

  private async executeRemotely(
      task: DistributedTask, deviceId: string): Promise<string> {
    const taskId = `remote_${deviceId}_${Date.now()}`
    this.taskQueue.push({
      ...task,
      taskId,
      deviceId,
      status: 'pending'
    })
    return taskId
  }

  // 查询任务状态
  getTaskStatus(taskId: string): TaskStatus | null {
    const task = this.taskQueue.find(t => t.taskId === taskId)
    if (!task) return null
    return {
      taskId: task.taskId,
      status: task.status,
      progress: task.progress,
      deviceId: task.deviceId ?? 'local'
    }
  }
}

interface DistributedTask {
  taskId: string
  type: string
  priority: 'low' | 'normal' | 'high' | 'urgent'
  payload: Object
  requiresGPU?: boolean
  requiresHighMemory?: boolean
  status: 'pending' | 'running' | 'completed' | 'failed'
  progress: number
  deviceId?: string
}

interface TaskStatus {
  taskId: string
  status: string
  progress: number
  deviceId: string
}

interface TaskCallback {
  onComplete: (result: Object) => void
  onError: (error: Error) => void
  onProgress: (progress: number) => void
}

7.5.3 5.4.3 任务优先级与资源管理

// 任务优先级调度器
class TaskPriorityScheduler {
  private highPriorityQueue: DistributedTask[] = []
  private normalPriorityQueue: DistributedTask[] = []
  private lowPriorityQueue: DistributedTask[] = []
  private maxConcurrentTasks: number = 3
  private runningTasks: number = 0

  // 添加任务
  enqueue(task: DistributedTask): void {
    switch (task.priority) {
      case 'urgent':
      case 'high':
        this.highPriorityQueue.push(task)
        break
      case 'normal':
        this.normalPriorityQueue.push(task)
        break
      case 'low':
        this.lowPriorityQueue.push(task)
        break
    }
    this.scheduleNext()
  }

  // 调度下一个任务
  private scheduleNext(): void {
    if (this.runningTasks >= this.maxConcurrentTasks) return

    let task: DistributedTask | undefined

    // 按优先级获取任务
    if (this.highPriorityQueue.length > 0) {
      task = this.highPriorityQueue.shift()
    } else if (this.normalPriorityQueue.length > 0) {
      task = this.normalPriorityQueue.shift()
    } else if (this.lowPriorityQueue.length > 0) {
      task = this.lowPriorityQueue.shift()
    }

    if (task) {
      this.runningTasks++
      this.executeTask(task)
    }
  }

  private async executeTask(task: DistributedTask): Promise<void> {
    try {
      task.status = 'running'
      // 执行任务...
      task.status = 'completed'
    } catch (error) {
      task.status = 'failed'
    } finally {
      this.runningTasks--
      this.scheduleNext()
    }
  }

  // 资源监控
  getResourceUsage(): ResourceUsage {
    return {
      cpuUsage: 0.45,
      memoryUsage: 0.62,
      networkBandwidth: 0.3,
      batteryLevel: 0.85
    }
  }
}

interface ResourceUsage {
  cpuUsage: number
  memoryUsage: number
  networkBandwidth: number
  batteryLevel: number
}

7.6 5.5 分布式通信

7.6.1 5.5.1 跨设备消息通信

import { distributedKVStore } from '@kit.ArkData'
import { common } from '@kit.AbilityKit'

// 跨设备消息通信服务
class CrossDeviceMessageService {
  private kvManager: distributedKVStore.KVManager | null = null
  private kvStore: distributedKVStore.SingleKVStore | null = null

  async initialize(context: common.UIAbilityContext): Promise<void> {
    try {
      // 创建KV管理器
      const kvManagerConfig: distributedKVStore.KVManagerConfig = {
        context: context,
        bundleName: 'com.example.distributedapp'
      }
      this.kvManager = distributedKVStore.createKVManager(kvManagerConfig)

      // 创建单版本KV存储
      const options: distributedKVStore.Options = {
        createIfMissing: true,
        encrypt: false,
        backup: false,
        autoSync: true,
        kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,
        securityLevel: distributedKVStore.SecurityLevel.S1
      }

      this.kvStore = await this.kvManager.getKVStore<distributedKVStore.SingleKVStore>(
        'message_channel', options
      )

      // 监听数据变更(跨设备同步)
      this.kvStore.on('change', (data: distributedKVStore.ChangeNotification): void => {
        // 处理来自其他设备的消息
        const insertEntries = data.insertEntries
        for (const entry of insertEntries) {
          console.info(`收到跨设备消息: ${entry.key}`)
          this.handleIncomingMessage(entry.key, entry.value.value as string)
        }
      })

    } catch (error) {
      console.error(`初始化消息服务失败: ${JSON.stringify(error)}`)
    }
  }

  // 发送消息到其他设备
  async sendMessage(targetDeviceId: string,
      message: CrossDeviceMessage): Promise<void> {
    if (!this.kvStore) {
      throw new Error('消息服务未初始化')
    }

    const key = `msg_${targetDeviceId}_${Date.now()}`
    const value = JSON.stringify(message)

    try {
      await this.kvStore.put(key, value)
      console.info(`消息已发送: ${key}`)
    } catch (error) {
      console.error(`消息发送失败: ${JSON.stringify(error)}`)
      throw error
    }
  }

  private handleIncomingMessage(key: string, value: string): void {
    try {
      const message: CrossDeviceMessage = JSON.parse(value)
      console.info(`处理消息: ${message.type} from ${message.senderId}`)
      // 根据消息类型进行处理
    } catch (error) {
      console.error(`消息解析失败: ${JSON.stringify(error)}`)
    }
  }

  async destroy(): Promise<void> {
    if (this.kvStore) {
      this.kvStore.off('change')
    }
    if (this.kvManager) {
      await this.kvManager.closeAllKVStores()
    }
  }
}

interface CrossDeviceMessage {
  type: 'text' | 'file' | 'command' | 'sync'
  senderId: string
  targetId: string
  content: string
  timestamp: number
  metadata?: Record<string, Object>
}

7.6.2 5.5.2 分布式数据对象

import { distributedObject } from '@kit.ArkData'

// 分布式数据对象示例
class SharedDocument {
  private session: distributedObject.Session | null = null

  // 创建分布式数据对象会话
  async createSession(context: Context, sessionId: string): Promise<void> {
    try {
      // 创建会话
      this.session = distributedObject.create({
        context: context,
        sessionId: sessionId
      })

      // 监听属性变更
      this.session.on('change', (prop: string, value: distributedObject.ObjectValue): void => {
        console.info(`属性 ${prop} 变更为: ${JSON.stringify(value)}`)
      })

      // 监听其他设备加入
      this.session.on('status', (sessionId: string,
          networkId: string, status: number): void => {
        if (status === 0) {
          console.info(`设备 ${networkId} 加入会话`)
        } else {
          console.info(`设备 ${networkId} 离开会话`)
        }
      })

    } catch (error) {
      console.error(`创建分布式会话失败: ${JSON.stringify(error)}`)
    }
  }

  // 设置共享属性
  setProperty(prop: string, value: string | number | boolean): void {
    if (!this.session) return
    this.session[prop] = value
  }

  // 获取共享属性
  getProperty(prop: string): distributedObject.ObjectValue {
    if (!this.session) return undefined
    return this.session[prop]
  }

  // 保存会话数据
  async save(): Promise<void> {
    if (!this.session) return
    return new Promise((resolve, reject) => {
      this.session!.save((error: Error) => {
        if (error) {
          reject(error)
        } else {
          resolve()
        }
      })
    })
  }

  // 释放会话
  release(): void {
    if (this.session) {
      this.session.off('change')
      this.session.off('status')
      this.session = null
    }
  }
}

7.6.3 5.5.3 设备间文件传输

import { transfer } from '@kit.CoreFileKit'

// 设备间文件传输管理器
class CrossDeviceFileTransfer {
  private transferClient: transfer.TransferClient | null = null

  async initialize(): Promise<void> {
    try {
      this.transferClient = await transfer.createTransferClient()
    } catch (error) {
      console.error(`创建传输客户端失败: ${JSON.stringify(error)}`)
    }
  }

  // 发送文件到远程设备
  async sendFile(targetDeviceId: string, filePath: string,
      onProgress: (progress: number) => void): Promise<void> {
    if (!this.transferClient) {
      throw new Error('传输客户端未初始化')
    }

    return new Promise((resolve, reject) => {
      const transferRequest: transfer.TransferRequest = {
        remoteDeviceId: targetDeviceId,
        transferMode: transfer.TransferMode.RELIABLE,
        files: [filePath]
      }

      this.transferClient!.startTransfer(transferRequest, {
        onProgress: (progress: transfer.TransferProgress) => {
          const percent = progress.processedSize / progress.totalSize
          onProgress(percent)
        },
        onComplete: () => {
          console.info('文件传输完成')
          resolve()
        },
        onFail: (errorCode: number) => {
          console.error(`文件传输失败: ${errorCode}`)
          reject(new Error(`传输失败: ${errorCode}`))
        }
      })
    })
  }

  // 接收文件
  async receiveFile(onFileReceived: (filePath: string) => void):
      Promise<void> {
    if (!this.transferClient) {
      throw new Error('传输客户端未初始化')
    }

    this.transferClient.on('fileReceived', (data: transfer.FileReceivedData) => {
      onFileReceived(data.filePath)
    })
  }

  async destroy(): Promise<void> {
    if (this.transferClient) {
      await this.transferClient.release()
    }
  }
}

7.7 5.6 分布式协同场景

7.7.1 5.6.1 多设备协同办公

// 协同办公场景 - 共享白板
@Component
struct CollaborativeWhiteboard {
  @State strokes: Stroke[] = []
  @State currentColor: string = '#000000'
  @State currentWidth: number = 3
  @State participants: Participant[] = []
  private session: distributedObject.Session | null = null

  build() {
    Column() {
      // 工具栏
      Row({ space: 12 }) {
        // 颜色选择
        ForEach(['#000000', '#FF0000', '#0000FF', '#00FF00', '#FF6600'],
          (color: string) => {
          Circle()
            .width(32)
            .height(32)
            .fill(color)
            .stroke(this.currentColor === color ? '#333333' : Color.Transparent)
            .strokeWidth(2)
            .onClick(() => {
              this.currentColor = color
            })
        }, (color: string) => color)

        Divider().vertical(true).height(24)

        // 参与者列表
        ForEach(this.participants, (p: Participant) => {
          Column() {
            Text(p.name.charAt(0))
              .fontSize(12)
              .fontColor(Color.White)
          }
          .width(28)
          .height(28)
          .borderRadius(14)
          .backgroundColor(p.color)
          .justifyContent(FlexAlign.Center)
        }, (p: Participant) => p.id)
      }
      .width('100%')
      .padding(8)

      // 白板画布
      Canvas(new CanvasRenderingContext2D(
        new RenderingContextSettings(true)))
        .width('100%')
        .layoutWeight(1)
        .backgroundColor(Color.White)
        .borderRadius(8)
    }
    .width('100%')
    .height('100%')
  }
}

interface Stroke {
  points: Point[]
  color: string
  width: number
  userId: string
}

interface Point {
  x: number
  y: number
}

interface Participant {
  id: string
  name: string
  color: string
}

7.7.2 5.6.2 跨设备投屏

// 跨设备投屏管理器
class ScreenCastManager {
  private isCasting: boolean = false
  private targetDeviceId: string = ''

  // 开始投屏
  async startScreenCast(targetDeviceId: string,
      options: ScreenCastOptions): Promise<void> {
    this.targetDeviceId = targetDeviceId
    this.isCasting = true

    try {
      // 获取屏幕数据
      const screenData = await this.captureScreen()

      // 建立投屏连接
      await this.establishCastConnection(targetDeviceId, {
        resolution: options.resolution,
        quality: options.quality,
        frameRate: options.frameRate
      })

      console.info(`投屏已开始: ${targetDeviceId}`)
    } catch (error) {
      this.isCasting = false
      console.error(`投屏启动失败: ${JSON.stringify(error)}`)
      throw error
    }
  }

  // 停止投屏
  async stopScreenCast(): Promise<void> {
    if (!this.isCasting) return

    try {
      await this.closeCastConnection()
      this.isCasting = false
      this.targetDeviceId = ''
      console.info('投屏已停止')
    } catch (error) {
      console.error(`停止投屏失败: ${JSON.stringify(error)}`)
    }
  }

  private async captureScreen(): Promise<Object> {
    // 屏幕捕获实现
    return {}
  }

  private async establishCastConnection(deviceId: string,
      options: ScreenCastOptions): Promise<void> {
    // 建立投屏连接
  }

  private async closeCastConnection(): Promise<void> {
    // 关闭投屏连接
  }
}

interface ScreenCastOptions {
  resolution: '720p' | '1080p' | '4k'
  quality: 'low' | 'medium' | 'high'
  frameRate: number
}

7.7.3 5.6.3 分布式输入(键鼠共享)

// 分布式输入管理器 - 键鼠共享
class DistributedInputManager {
  private isShared: boolean = false
  private hostDeviceId: string = ''
  private connectedDevices: string[] = []

  // 启用键鼠共享
  async enableInputSharing(): Promise<void> {
    this.isShared = true
    console.info('键鼠共享已启用')

    // 注册输入事件监听
    this.registerInputListeners()
  }

  // 禁用键鼠共享
  async disableInputSharing(): Promise<void> {
    this.isShared = false
    this.unregisterInputListeners()
    console.info('键鼠共享已禁用')
  }

  private registerInputListeners(): void {
    // 监听鼠标移动事件
    // 当鼠标移动到屏幕边缘时,自动切换到目标设备
  }

  private unregisterInputListeners(): void {
    // 注销监听
  }

  // 切换输入焦点到指定设备
  async switchInputFocus(targetDeviceId: string): Promise<void> {
    if (!this.isShared) {
      throw new Error('键鼠共享未启用')
    }

    console.info(`切换输入焦点到: ${targetDeviceId}`)
    // 实现输入焦点切换逻辑
  }

  // 获取当前输入焦点设备
  getCurrentFocusDevice(): string {
    return this.hostDeviceId
  }
}

7.7.4 5.6.4 典型应用场景分析

场景一:多设备协同编辑

多个用户在不同设备上同时编辑同一文档,通过分布式数据对象实现实时同步:

// 协同编辑场景
@Component
struct CollaborativeEditor {
  @State documentContent: string = ''
  @State collaborators: string[] = []
  @State cursorPositions: CursorPosition[] = []

  build() {
    Column() {
      // 协作者状态栏
      Row() {
        ForEach(this.collaborators, (name: string) => {
          Text(name)
            .fontSize(12)
            .fontColor(Color.White)
            .backgroundColor('#4CAF50')
            .borderRadius(12)
            .padding({ left: 8, right: 8, top: 4, bottom: 4 })
            .margin({ right: 4 })
        }, (name: string) => name)
      }
      .width('100%')
      .padding(8)

      // 编辑区域
      TextArea({ text: this.documentContent, placeholder: '开始编辑...' })
        .layoutWeight(1)
        .fontSize(16)
        .padding(12)
        .onChange((value: string) => {
          this.documentContent = value
          // 同步变更到其他设备
          this.syncDocumentChange(value)
        })
    }
    .width('100%')
    .height('100%')
  }

  private syncDocumentChange(content: string): void {
    // 通过分布式数据对象同步文档变更
  }
}

interface CursorPosition {
  userId: string
  userName: string
  position: number
  color: string
}

7.8 本章小结

本章全面介绍了HarmonyOS的分布式能力:

  1. 分布式软总线:理解了软总线的分层架构,掌握了设备发现、设备认证和通信协议选择的方法。软总线是HarmonyOS分布式能力的基石,屏蔽了底层通信差异。

  2. 分布式设备虚拟化:掌握了超级终端的概念,学会了设备能力声明与查询,理解了跨设备任务调度的原理。

  3. 跨设备迁移:深入理解了迁移流程和生命周期回调(onSaveData/onRestoreData),掌握了迁移权限配置和错误处理,实现了视频播放的跨设备迁移。

  4. 分布式任务调度:学会了跨设备Ability启动、任务优先级管理和资源调度策略。

  5. 分布式通信:掌握了跨设备消息通信、分布式数据对象、文件传输等核心通信技术。

  6. 分布式协同场景:了解了多设备协同办公、跨设备投屏、键鼠共享等典型应用场景的实现思路。


7.9 练习题

7.9.1 一、单选题

1. HarmonyOS分布式软总线的核心作用是什么?

A. 提供UI渲染能力 B. 屏蔽底层物理通信协议差异,提供统一的分布式通信能力 C. 管理应用的生命周期 D. 处理用户输入事件

答案:B

解析: 分布式软总线是HarmonyOS的核心底座,它屏蔽了底层物理通信协议(WiFi、BLE、USB等)的差异,为上层应用提供统一的分布式通信能力,包括设备发现、设备认证、连接管理和消息通信等。


2. 在跨设备迁移(Continuation)中,源设备保存迁移数据的回调方法是?

A. onRestoreData() B. onContinue() C. onSaveData() D. onMigrate()

答案:C

解析: 跨设备迁移的生命周期中,源设备通过 onSaveData() 回调保存需要迁移的数据,目标设备通过 onRestoreData() 回调恢复数据,onContinue() 在迁移完成后回调。


3. 以下哪个权限是跨设备迁移必须声明的?

A. ohos.permission.INTERNET B. ohos.permission.MIGRATE_ABILITY C. ohos.permission.CAMERA D. ohos.permission.WRITE_MEDIA

答案:B

解析: 跨设备迁移需要声明 ohos.permission.MIGRATE_ABILITY 权限,同时需要在Ability配置中设置 continueAbility: true


7.9.2 二、多选题

4. 以下哪些是HarmonyOS分布式软总线的核心能力?

A. 设备发现 B. 设备认证 C. UI渲染 D. 消息通信 E. 连接管理

答案:A、B、D、E

解析: 分布式软总线的核心能力包括设备发现、设备认证、连接管理和消息通信。UI渲染不属于软总线的能力范畴,而是ArkUI框架的职责。


5. 关于分布式数据对象(distributedObject)的描述,以下哪些是正确的?

A. 可以在多个设备间共享数据 B. 支持属性变更的实时通知 C. 数据自动在所有设备间同步 D. 需要创建Session来管理共享数据 E. 只能共享基本数据类型

答案:A、B、D

解析: 分布式数据对象支持跨设备数据共享(A正确),支持属性变更通知(B正确),需要通过Session管理(D正确)。数据同步需要配置同步策略,不是完全自动的(C不完全正确)。分布式数据对象支持多种数据类型,不仅限于基本类型(E错误)。


7.9.3 三、判断题

6. 跨设备迁移时,源设备和目标设备必须登录同一个华为账号。

答案:正确

解析: 跨设备迁移要求源设备和目标设备属于同一用户(登录同一华为账号),并且在同一分布式网络中。这是安全机制的要求,防止数据被迁移到非授权设备。


7. 分布式软总线只能使用WiFi进行设备间通信。

答案:错误

解析: 分布式软总线支持多种通信协议,包括WiFi、蓝牙(BLE)、USB、以太网等。软总线会根据网络环境和业务需求自动选择最优的通信链路。


8. 在跨设备迁移中,onSaveData 方法中可以传输任意大小的数据。

答案:错误

解析: 迁移数据有大小限制,过大的数据可能导致迁移失败。建议只传输必要的状态数据,大文件应通过其他方式(如分布式文件传输)处理。