【鸿蒙心迹】分布式跨设备协同实战:让任务在设备间无缝流转

摘要:本文围绕鸿蒙分布式跨设备协同能力展开,从整体认知、底层原理到实战落地三层递进。先厘清分布式协同与传统多设备的本质差异,再拆解设备发现、可信设备组与任务流转(迁移流转、协同流转)的核心机制,最后以"手机阅读→平板续读"为例,完整演示权限声明、设备发现、任务迁移与目标端接收的四步实现,并给出设备发现为空、continueMission 报 401、流转后数据丢失等典型坑点的排查与解决方案,帮助有鸿蒙基础的开发者快速跑通跨设备协同。

“分布式"是鸿蒙最招牌的能力,也是最容易让人困惑的概念。文档里写的"超级终端”“任务流转”"硬件互助"听起来都很厉害,但真正动手做的时候,发现设备发现调不通、流转能力配不上、跨设备调用报权限错误,每一步都是坎。我第一次做分布式协同时,两台设备就是发现不了彼此,折腾了两天才发现是同一WiFi网络但不在同一可信设备组里。

如果你有鸿蒙应用开发基础,想让你的应用支持跨设备协同,但对分布式能力体系不熟悉,这篇正好适合你。读完后你会知道:分布式能力的整体架构、设备发现与可信组的管理、任务流转的完整实现流程。

本文分三层来讲:第一层建立对分布式协同的整体认知;第二层拆解设备发现和任务流转的底层原理;第三层是完整的实战落地和踩坑排错。

在这里插入图片描述

图1:分布式跨设备协同运行效果——手机、平板、智慧屏三端无缝流转

入门认知:分布式协同到底"协"了什么

一句话定义

分布式跨设备协同是鸿蒙提供的多设备协作能力——应用可以在不同设备间无缝流转任务、共享数据、互助硬件,让多台设备像一个设备一样工作。

打个比方:普通多设备就像几个人各自干活——你干你的,我干我的;分布式协同就像一个团队——任务可以交接、工具可以共享、信息可以同步,大家协同完成一件事。

分布式协同 vs 传统多设备

对比维度传统多设备分布式协同
设备关系各自独立组成超级终端
任务流转手动重新操作一键无缝流转
数据共享通过云端中转端到端直接共享
硬件使用各用各的可调用其他设备硬件
开发模式每端单独开发一次开发多端部署

表1:传统多设备与分布式协同的核心差异

全景图示

分布式能力

设备发现

设备可信组

任务流转

数据共享

硬件互助

DeviceManager

SoftBus

DistributedScheduler

分布式数据管理

分布式硬件管理

图2:分布式能力的完整体系架构

适用边界

分布式协同适合:多设备办公(手机→平板→智慧屏)、跨设备媒体播放、智能家居控制、跨设备文件传输。不适合:单设备就能完成的简单任务、对延迟极其敏感的实时操作。

进阶原理:设备发现与任务流转机制

设备发现到底怎么发现?

分布式协同的第一步是设备发现,核心通过 DeviceManager 模块实现:

阶段API作用触发时机
注册监听deviceManager.createDeviceManager创建设备管理实例应用启动时
开始发现startDeviceDiscovery搜索附近可信设备用户触发协同时
设备回调onDeviceFound发现新设备时回调发现过程中
停止发现stopDeviceDiscovery停止搜索找到目标设备后
设备认证authenticateDevice加入可信设备组首次连接新设备

表2:设备发现的核心API链路

设备发现的完整时序如下:

"目标设备""系统超级终端""DeviceManager""应用""目标设备""系统超级终端""DeviceManager""应用""createDeviceManager()""返回 dmInstance""startDeviceDiscovery()""查询可信设备组""返回可信设备列表""广播发现请求""响应设备信息""onDeviceFound 回调""stopDeviceDiscovery()"

图4:设备发现的完整调用时序

可信设备组是什么?

很多人卡在"设备发现不到"这一步,根源往往是不理解可信设备组。

同一可信组

同一可信组

不在可信组

可直接发现

无法发现

设备A

设备B

设备C

设备D

图3:可信设备组与设备发现的关系

[注意] 两台设备必须在同一可信设备组中才能互相发现和协同。可信组通过用户在系统设置中"超级终端"手动建立,或者通过 authenticateDevice API在应用内引导建立。

任务流转的两种模式

流转模式含义典型场景API
迁移流转任务从A设备完全迁移到B设备手机看视频→流转到智慧屏继续看continueMission
协同流转A和B设备同时显示不同界面手机做控制器→平板做显示startRemoteMission

表3:两种任务流转模式对比

两种流转模式的差异可以用下图直观对比:

协同流转 startRemoteMission

实时协同

手机:控制器界面

平板:显示界面

迁移流转 continueMission

迁移后退出

手机:任务运行

任务整体迁移

平板:继续运行

手机:释放任务

图5:迁移流转与协同流转的差异对比

常见误区

误区1:以为设备发现是自动的

很多人以为应用启动后自动就能发现附近设备,其实必须主动调用 startDeviceDiscovery,而且用户需要在系统设置中开启"允许被发现"。

误区2:用云端中转代替分布式数据管理

有人为了简单,用HTTP接口把数据传到云端再从另一台设备拉取。这完全绕过了分布式能力,延迟高、依赖网络、体验差。正确做法是用分布式数据管理(distributedDataStore),端到端直接同步。

高级应用:从零实现一个跨设备阅读流转

实战步骤

以"手机阅读→流转到平板继续阅读"为例:

整个实战流程可以概括为四个步骤:

否

是

第一步:声明四个分布式权限

第二步:实现设备发现

第三步:发起任务迁移流转

第四步:目标设备 onContinue 接收

参数类型是否一致

做类型转换后恢复状态

直接恢复阅读进度

流转完成

图6:跨设备阅读流转的四步实现流程

第一步:声明分布式权限

在 module.json5 中声明:

{
  "module": {
    "requestPermissions": [
      { "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE" },
      { "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO" },
      { "name": "ohos.permission.ACCESS_SERVICE_DISTRIBUTED_DEVICE" },
      { "name": "ohos.permission.DISTRIBUTED_DATASYNC" }
    ]
  }
}

[注意] 这四个权限缺一不可。少了任何一个,设备发现或流转都会失败但不会报明确错误,只能看到"无可用设备"。

第二步:实现设备发现

import { deviceManager } from '@kit.DistributedServiceKit'

let dmInstance: deviceManager.DeviceManager

// 创建设备管理实例
deviceManager.createDeviceManager('com.example.readapp', (err, dm) => {
  if (err) {
    console.error('createDeviceManager failed: ' + JSON.stringify(err))
    return
  }
  dmInstance = dm
  // 注册设备状态变化监听
  dmInstance.on('deviceStateChange', (state) => {
    if (state.type === deviceManager.DeviceStateChangeType.ONLINE) {
      // 设备上线,刷新可用设备列表
      this.refreshDeviceList()
    }
  })
})

// 开始发现设备
function startDiscovery(): void {
  let discoveryInfo: deviceManager.SubscribeInfo = {
    subscribeId: 1,
    mode: deviceManager.DiscoveryMode.DISCOVER_MODE_ACTIVE,
    capability: deviceManager.DiscoveryFilter.FILTER_TYPE_ALL
  }
  dmInstance.startDeviceDiscovery(discoveryInfo)
}

// 发现设备回调
dmInstance.on('deviceFound', (device) => {
  // device.deviceName, device.deviceId, device.deviceType
  this.availableDevices.push(device)
})

第三步:实现任务迁移流转

import { distributedMissionManager } from '@kit.DistributedMissionKit'

function migrateToTarget(targetDeviceId: string): void {
  let continueInfo: distributedMissionManager.ContinueInfo = {
    deviceId: targetDeviceId,
    bundleName: 'com.example.readapp',
    // 传递当前阅读进度
    parameters: {
      bookId: this.currentBook.id,
      chapterIndex: this.currentChapter,
      scrollPosition: this.scrollOffset
    }
  }
  distributedMissionManager.continueMission(continueInfo)
    .then(() => {
      // 流转成功,本端可退出或进入协同模式
      console.info('Mission migrated successfully')
    })
    .catch((err) => {
      console.error('Migrate failed: ' + JSON.stringify(err))
    })
}

第四步:目标设备接收流转

在目标设备的 Ability 中处理流转入口:

export default class ReadAbility extends UIAbility {
  onContinue(want: Want): void {
    // 从want.parameters中恢复阅读进度
    let bookId = want.parameters?.bookId as string
    let chapterIndex = want.parameters?.chapterIndex as number
    let scrollPosition = want.parameters?.scrollPosition as number

    // 恢复阅读状态
    this.restoreReadingState(bookId, chapterIndex, scrollPosition)
  }
}

踩坑排错

坑1:设备发现列表为空

现象:调用 startDeviceDiscovery 后,onDeviceFound 回调始终不触发。

原因排查清单:

  1. 两台设备是否在同一WiFi网络?→ 必须同一局域网
  2. 两台设备是否在同一可信设备组?→ 系统设置→超级终端中检查
  3. 目标设备的"允许被发现"是否开启?→ 系统设置→超级终端→发现设置
  4. 应用是否声明了完整的四个分布式权限?→ 检查module.json5

坑2:continueMission 报错 401

现象:调用 continueMission 时报 401 错误码。

原因:目标设备上没有安装同bundle的应用,或者版本不一致。

解决:确保两端安装了相同版本的应用,bundleName完全一致。

坑3:流转后数据丢失

现象:任务流转到目标设备后,阅读进度没有恢复,从头开始显示。

原因:onContinue 中获取 want.parameters 时,数据类型发生了变化(数字变成了字符串)。

解决:在 onContinue 中做类型转换,不要假设参数类型和发送时一致:

onContinue(want: Want): void {
  let bookId = String(want.parameters?.bookId ?? '')
  let chapterIndex = Number(want.parameters?.chapterIndex ?? 0)
  let scrollPosition = Number(want.parameters?.scrollPosition ?? 0)
  this.restoreReadingState(bookId, chapterIndex, scrollPosition)
}

最佳实践

  • 权限声明要完整:四个分布式权限缺一不可
  • 设备发现要主动:不要等系统自动发现,主动调用startDeviceDiscovery
  • 参数类型要转换:流转传递的参数类型可能变化,接收时做类型转换
  • 版本必须一致:两端应用版本不一致会导致流转失败
  • 降级处理要准备:流转失败时给用户手动操作的选择,不要只报错

总结

核心要点:

  1. 分布式协同的核心是让多台设备组成超级终端,实现任务流转、数据共享、硬件互助
  2. 设备发现的前提是同一可信设备组,通过DeviceManager API实现
  3. 任务流转有两种模式:迁移流转(完全迁移)和协同流转(同时显示)
  4. 四个分布式权限缺一不可,少了任何一个都会导致功能异常但不报明确错误

最佳实践清单:

  • 权限声明要完整,四个分布式权限缺一不可
  • 设备发现要主动调用,不要等系统自动推送
  • 流转参数接收时做类型转换,不要假设类型一致
  • 两端应用版本必须一致,否则流转会失败
  • 流转失败要有降级方案,给用户手动操作的选择

你在分布式协同开发中遇到过什么坑?评论区聊聊。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐