做鸿蒙分布式应用,别绕开超级终端这个入口
摘要 超级终端是鸿蒙系统的核心能力,开发者无法直接开发类似功能,但可以通过适配分布式能力提升应用体验。本文详细解析了超级终端的技术实现: 核心机制:超级终端本质是系统级的设备协同入口,依赖分布式设备发现、跨设备启动、状态迁移等能力 开发要点: Ability需声明continuable:true支持流转 通过设备管理API获取协同设备信息 使用startAbility实现跨设备启动 实现onCon

摘要(背景与现状)
在鸿蒙生态里,很多开发者一开始都会问一个问题:
超级终端能不能开发?
能不能自己做一个类似的功能?
答案其实很明确:
超级终端是系统级能力,不是第三方 App 可以实现的功能模块。
但这并不代表开发者什么都做不了。
真实情况是:
- 超级终端本身是系统 UI
- 真正决定体验好不好的,是你的应用是否支持分布式调度和状态流转
现在很多应用在超级终端里表现很“傻”,
拖过去只是重新打开一个页面,状态全没了,
问题并不在超级终端,而在应用本身没有按分布式方式设计。
引言(发展情况与应用场景)
从 HarmonyOS 2.0 到现在,
超级终端已经不再是“展示设备”的功能了,而是一个统一的设备协同入口。
用户在做的事情其实很简单:
- 把应用从手机拖到平板
- 把当前任务流转到大屏
- 把数据和状态无感知地迁移过去
但系统背后做的事情并不简单,它依赖的是:
- 分布式设备发现
- 跨设备 Ability 启动
- 应用状态迁移
- 分布式任务和数据同步
开发者真正要做的,是把自己的应用设计成“可以被这一套机制调度的能力”。
先说清楚:超级终端在开发层面到底是什么
从开发者视角看,可以把超级终端理解成:
系统帮你完成了“选设备 + 触发跨设备启动”的那一步
真正落到你代码里的,其实只有这几件事:
- 你的 Ability 是否允许跨设备启动
- 是否支持状态流转
- 是否能正确恢复数据
换句话说:
- UI 是系统的
- 能不能跑得好,是你的设计问题
让应用“能被超级终端拖动”的前置条件
Ability 必须声明支持流转
这是第一道门槛,没这个,后面全白搭。
module.json5 示例
{
"module": {
"abilities": [
{
"name": "MainAbility",
"type": "page",
"launchType": "standard",
"continuable": true
}
]
}
}
这里的 continuable: true 表示:
- 这个 Ability 允许被系统迁移
- 超级终端里才能“拖得动你”
很多人测试不成功,问题就卡在这里。
设备发现:超级终端设备从哪来
系统展示 vs 应用获取
超级终端里的设备列表是系统统一维护的,
但你在应用里同样可以拿到这些设备信息。
设备发现示例代码
import deviceManager from '@ohos.distributedDeviceManager';
let dm = deviceManager.createDeviceManager('com.example.superdemo');
dm.on('deviceStateChange', (data) => {
console.info('device state change:', JSON.stringify(data));
});
你能拿到的信息包括:
- deviceId
- 设备上下线状态
- 设备类型
这里的 deviceId 非常关键,
后面跨设备启动 Ability 就靠它。
跨设备启动:拖过去的本质行为
拖拽在系统里发生了什么
当用户在超级终端里把应用拖到另一台设备,
系统本质上只做了一件事:
在目标设备上调用
startAbility
跨设备启动示例代码
import featureAbility from '@ohos.ability.featureAbility';
featureAbility.startAbility({
want: {
deviceId: 'remote-device-id',
bundleName: 'com.example.superdemo',
abilityName: 'MainAbility',
parameters: {
source: 'super_terminal',
time: Date.now()
}
}
});
这里你可以注意几个点:
deviceId决定启动在哪台设备parameters用来传递上下文信息- 这一步只负责“拉起应用”
如果只做到这里,体验会非常像“重新打开 App”。
状态流转:体验好不好的分水岭
真正决定体验差异的,是这一部分。
为什么需要状态流转
如果没有状态迁移:
- 页面重新加载
- 数据全丢
- 用户感觉是两个独立的 App
而超级终端希望做到的是:
- 页面接着刚才的操作
- 数据原封不动带过去
实现 Continuation 接口
Ability 示例
import Continuation from '@ohos.continuation';
export default class MainAbility extends Continuation {
currentData: string = 'default';
onContinue(wantParams) {
wantParams['data'] = this.currentData;
wantParams['page'] = 'detail';
return true;
}
}
onContinue 会在流转发生时被系统调用:
- 你决定要传什么数据
- 返回 true 表示允许流转
在目标设备恢复状态
onCreate(want) {
if (want?.parameters?.data) {
this.currentData = want.parameters.data;
}
}
这一步决定:
- 页面是不是“接着来”
- 数据是不是完整恢复
结合实际场景的应用示例
下面用三个真实容易落地的场景来说明。
场景一:手机拍照,拖到平板继续编辑
场景说明
- 手机负责采集
- 平板负责编辑
- 用户不想重新选择图片
核心思路
- 手机端保存图片路径
- 流转时通过 Continuation 传递路径
- 平板端直接进入编辑页
示例代码(传递图片路径)
onContinue(wantParams) {
wantParams['imagePath'] = this.currentImagePath;
wantParams['page'] = 'editor';
return true;
}
onCreate(want) {
if (want.parameters?.imagePath) {
this.loadImage(want.parameters.imagePath);
}
}
场景二:手表采集数据,拖到手机分析
场景说明
- 手表算力有限
- 手机负责数据分析和展示
示例思路
- 手表端缓存采集结果
- 流转时一次性带过去
- 手机端直接渲染分析页面
onContinue(wantParams) {
wantParams['healthData'] = this.cacheData;
return true;
}
场景三:大屏展示,拖到手机控制
场景说明
- 大屏负责展示内容
- 手机作为控制器
示例代码(传递当前状态)
onContinue(wantParams) {
wantParams['playIndex'] = this.currentIndex;
wantParams['mode'] = 'controller';
return true;
}
QA 环节(高频问题)
Q1:能不能自己做一个超级终端?
不能。
系统级 UI,不对第三方开放。
Q2:只写跨设备启动可以吗?
可以,但体验很差,
基本等于“重新打开一个 App”。
Q3:必须多设备测试吗?
必须。
单设备永远看不出流转问题。
总结
从开发角度看,超级终端不是一个 API,
而是一种应用设计结果的集中体现。
你真正要做的不是研究超级终端 UI,
而是把应用设计成:
- Ability 可以跨设备启动
- 状态可以被迁移
- 数据可以被恢复
只要这三点做好了,
你的应用在超级终端里的体验自然就“像系统应用”。
更多推荐



所有评论(0)