鸿蒙分布式能力:软总线与流转现状

《鸿蒙分布式能力:软总线与流转现状》

要点

“流转”是鸿蒙最有辨识度的卖点:手机上看一半的文章,点一下就能到平板接着看。卖点归卖点,开发者真正拿到手的能力是有边界的。这篇把 API 12(HarmonyOS NEXT 5.0)下三方应用能碰到的分布式能力盘一遍:软总线是什么、流转两条路线各开放到什么程度、一个最小跨端迁移示例怎么写、什么业务值得做。

本文不做:多端协同的完整实现(跨设备远程调用,权限门槛很高,后面如实说明)、穿戴与 IoT 设备的流转细节、软总线底层协议。范围就是三方应用视角的”现状盘点 + 迁移落地”。真机与签名的准备在上架篇——分布式测试没有模拟器可用,必须两台真机。

软总线:开发者看到的那一层

分布式软总线是华为对”设备发现、认证、组网、传输”的一层封装。对开发者它几乎是隐形的:业务代码里不出现 IP 地址,不出现 Wi-Fi 还是蓝牙的选择,只出现”设备列表”和”某台设备的标识”。拆开看它是四个环节的串联:

  • 发现:同一账号下的邻近设备互相找到,Wi-Fi 与蓝牙多通道并用;
  • 认证:设备对凭据互验,建立可信关系;
  • 组网:认证过的设备组成一张虚拟网,应用看到的”设备列表”就是它;
  • 传输:业务数据在虚拟网上走,通道按数据特性由系统选择。

这四段对应用全是黑盒,你感知到的只有”设备出现了、迁移成功了或失败了”,应用层要做的事只剩两件:订阅设备上下线,发起迁移或调用。

这层封装的实际意义是:流转类功能不要求你写任何网络编程。你处理的始终是 Want 参数里的键值对,搬运过程全部由系统完成。代价是你对传输没有控制权——超时、重试、失败兜底的策略都是系统的,应用只能接收结果。所以本文的示例代码量很小,功夫都在”状态怎么收拢”上。

API 12 的流转版图:如实说

官方语境里的”流转”分两条路线,对三方应用的开放程度差别很大:

  • 跨端迁移(应用接续):把应用当前状态搬到另一台设备继续。API 12 对三方应用开放,主要覆盖手机、平板、2in1 三类形态之间的迁移,这是本文的主菜。
  • 多端协同:多台设备各干各的、协同完成一件事(跨设备远程调用、分布式 UI)。远程调用另一端的能力、把一段 UI 投到另一端,这两类形态都需要系统场景级的授权,API 12 下三方应用的申请通道基本是关着的,短期内别把协同排进计划。
  • 穿戴与 IoT 设备:以系统级场景为主(手表接听手机来电这类),三方应用能做的有限。

还有一组使用前提,缺一个流转入口就不出现:两端设备都运行 HarmonyOS NEXT(API 12+)、登录同一华为账号、在同一局域网或通过蓝牙就近完成组网。这些是系统层硬约束,代码写对了、设备条件不满足,迁移照样不发生,而且通常表现为”入口压根不出现”而不是报错——排查时先查条件再查代码。

最小跨端迁移示例

迁移在代码侧只做两件事:声明应用可迁移,以及在回调里搬运状态。

第一步:声明 continuable

// entry/src/main/module.json5
"abilities": [
  {
    "name": "EntryAbility",
    "continuable": true,
    // 其余常规配置
  }
]

第二步:源端 onContinue 搬运状态

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

export default class EntryAbility extends UIAbility {
  onContinue(wantParam: Record<string, Object>): AbilityConstant.OnContinueResult {
    // 只搬恢复页面所需的最小状态:当前页、阅读位置、表单草稿
    wantParam['currentPage'] = this.currentPageIndex;
    wantParam['readingPos'] = this.readingPos;
    return AbilityConstant.OnContinueResult.AGREE;
  }
}

迁移被触发时,onContinue 在源端调用,同步保存数据并表态:AGREE 放行,REJECT 拒绝。注意它是同步的——数据此刻就得备好,别指望在这里现做一次异步查询,异步数据没到就返回,搬过去的就是空值。

第三步:目标端恢复

onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
    this.restore((want.parameters?.currentPage as number) ?? 0);
  }
}

onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  // 目标端应用已存在时走这里,逻辑与 onCreate 保持一致
  if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
    this.restore((want.parameters?.currentPage as number) ?? 0);
  }
}

验收路径(两台 NEXT 真机、同账号、同局域网):手机端打开应用进入第二页,任务中心长按应用卡片找到流转入口,选目标设备;预期平板端自动拉起应用并落在第二页,手机端应用退到后台。恢复到”哪个页面、哪条数据”完全取决于 wantParam 里塞了什么——塞得少,平板上就是冷启动首页;塞得全,才谈得上”接续”。

关于触发入口多说一句:系统提供的入口(任务中心卡片等)随系统版本演进,应用也可以在界面里自定义”移到平板继续”之类的按钮,具体接口以你手上的 SDK 文档为准。我的建议是先用系统入口把链路验证通,再考虑自定义入口——入口只是触发器,恢复逻辑才是要做对的部分。

数据搬运的边界

wantParam 是键值对,体量要克制,官方口径就是搬”最小状态”:页面栈位置、表单草稿、播放进度这类小数据。大文件和结构化大数据别硬塞——正确路线是 wantParam 里放一个引用键,目标端拿到键后从分布式文件或分布式数据对象取正文。分布式数据对象能把一个对象在多端间自动同步,是接大数据的正规通道,展开写是另一篇的事,这里给个方向。

拿阅读类应用举例,一次完整接续的状态清单长这样:

  • currentPage:当前章节或页面标识;
  • readingPos:页内滚动位置或播放进度;
  • bookId 与来源键:目标端凭它从书架或分布式文件取回正文;
  • 字号、夜间模式这类用户偏好:不塞进来——那是”这个用户”的状态,走首选项同步更合适。

清单最后一项是个判断题:这个状态属于”这个任务实例”,还是属于”这个用户”?前者才进 wantParam,后者交给系统已有的同步通道,混着塞是迁移参数膨胀的主要来源。

与多端开发的取舍

先泼冷水:迁移不是多端适配的替代品,它的地基恰恰是多端适配。页面在手机上排版正常,迁到平板上还是手机排版,这次”接续”就是一次糟糕的体验——断点布局、Navigation 分栏在平板上的正确形态,都是ArkUI 布局与导航篇讨论过的内容。先让应用在两台设备上都”是个正经应用”,再谈迁移。

什么时候值得做迁移,我的判断标准是任务的连续性:阅读进度、长表单填写、文档编辑、播放位置——用户在 A 设备上有”未完成的任务”,B 设备更大或更便携,迁移有真实价值。反例是强设备特性的场景(拍照、传感器、通话),状态搬过去也没法继续,做了只会扩大维护面。

成本面也要诚实:迁移功能本身代码量不大,上面三步就是骨架,真正的成本在”状态序列化”——你要把页面状态收拢成一组可搬运的键值,这要求应用的状态管理本身是干净的。状态散落在各组件私有权里、没有集中收口的应用,做迁移等于把状态管理重构一遍。这不算坏事,但要计入工时。

常见坑

  • continuable 忘了配:onContinue 写得再好也不会被触发,系统根本不认这个应用可迁移。
  • 状态没塞够:目标端落在首页而非业务页面——多数时候不是迁移失败,是 wantParam 里压根没放页面参数。
  • onNewWant 漏处理:目标端应用已存在时走 onNewWant,只写 onCreate 会漏掉一半路径。
  • onContinue 里做异步操作:它要同步返回结果,异步数据没到就返回,搬过去的是空值。
  • 拿模拟器测分布式:软总线发现与组网在本地模拟器上不可用,流转必须两台真机、真账号、真网络环境。
  • 把大文件塞 wantParam:键值对通道装不下大数据,迁移失败或被截断,走分布式文件。

验收清单

  • 两台 NEXT 真机(手机 + 平板)同账号同局域网,从任务中心发起迁移,目标端恢复到源端同一页面且数据完整。
  • 源端 onContinue 返回 AGREE,目标端 onCreate 与 onNewWant 两条路径都能收到 CONTINUATION 并正确恢复。
  • 反向迁移(平板 → 手机)同样走通,说明恢复逻辑不依赖设备方向。
  • 条件不满足时(退出账号、断开局域网)流转入口消失,应用本身无异常、无崩溃。
  • 迁移中途断网(发起后立刻关闭源端网络):目标端不出现半初始化页面,应用可正常冷启动。
  • wantParam 只放键值小数据;业务若有大数据接续,走分布式文件或分布式数据对象并有验证。
  • 迁移后源端应用退到后台,不残留可交互的半死状态。

落地顺序建议:先按上架篇把签名与真机调试材料备齐(分布式测试对真机账号有要求),再回布局与导航篇确认应用在平板上的断点形态,最后才叠迁移逻辑——顺序反了,你会分不清问题出在流转链路还是页面本身。

本文数据核对时间:2025-04-25:HarmonyOS NEXT 5.0(2024-10-22 商用发布)+ API 12;跨端迁移(应用接续)以 continuable 声明 + UIAbility.onContinue + LaunchReason.CONTINUATION 恢复为官方口径,支持范围以手机/平板/2in1 为主,多端协同对三方应用权限受限为现状口径,均以华为开发者文档当日版本为准。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇