在“轻规划”这类个人规划应用里,用户可能在通勤地铁上用手机编辑五年后的愿景信,回家后希望把书写现场流转到鸿蒙平板,用更大屏幕和实体键盘继续写。HarmonyOS NEXT 提供原生应用级流转底座 Ability Kit(应用接续):两台设备登录同一华为账号、处于近场范围时,平板 Dock 栏会自动浮现手机端“轻规划”流转图标,点击后手机端编辑界面关闭,平板端以相同输入内容甚至光标停留位置打开。下面围绕 EntryAbility 重写 onContinue,拆解源端封包、宿端解析、UI 路由恢复和防闪屏处理。
一、接续管线与职责划分
应用流转由系统底层通过分布式总线在设备间热备数据。源端通过回调把状态写入 Want 数据包,宿端在冷启动或热拉起时解析此包重建界面。核心职责可以拆成四层:源端 EntryAbility.onContinue 负责封包;宿端 EntryAbility.onCreate/onNewWant 负责解包;AppStorage 暂存并传递编辑现场;UI 主入口监听恢复标志并做路由重定向。
二、源端封包:在 onContinue 中写入 wantParams
要让对端还原流转前状态,需要在源端 Ability 的 onContinue 钩子中,把当前业务页面路由、编辑文本草稿和光标偏移量全部存入 wantParams。示例中先从 AppStorage 读取 currentRoute、visionLetterDraft、visionInputCursorOffset,再写入 targetRoute、editingDraft、cursorOffset。正常返回 AGREE 表示同意流转;内部严重错误时返回 REJECT 拦截流转,避免对端拿到空白数据。
- import { UIAbility, Want, AbilityConstant } from '@kit.AbilityKit';
- export default class EntryAbility extends UIAbility {
- // 当应用被流转时,系统会自动触发此回调
- onContinue(wantParams: Record<string, Object>): AbilityConstant.OnContinueResult {
- try {
- // 1. 从 AppStorage 全局临时缓存中读取当前的编辑现场状态
- const currentRoute = AppStorage.get<string>('currentRoute') || 'VisionEditPage';
- const editingDraft = AppStorage.get<string>('visionLetterDraft') || '';
- const selectionOffset = AppStorage.get<number>('visionInputCursorOffset') || 0;
- // 2. 将数据塞入流转打包参数中
- wantParams['targetRoute'] = currentRoute;
- wantParams['editingDraft'] = editingDraft;
- wantParams['cursorOffset'] = selectionOffset;
- console.info("EntryAbility", "onContinue context saved successfully.");
- // 3. 返回 AGREE 表示同意该流转请求
- return AbilityConstant.OnContinueResult.AGREE;
- } catch (err) {
- console.error("EntryAbility", "onContinue save state failed", err);
- // 若发生内部严重错误,返回 REJECT 拦截流转,防止对端拿到空白数据
- return AbilityConstant.OnContinueResult.REJECT;
- }
- }
- }
复制代码
三、宿端解包:区分冷启动与热启动,判断 CONTINUATION
接收端系统会自动冷启动或热激活“轻规划”。需要在 onCreate(冷启动)或 onNewWant(热启动)中拦截 Want 参数,并判断 launchParam.launchReason 是否为 AbilityConstant.LaunchReason.CONTINUATION。命中后提取 targetRoute、editingDraft、cursorOffset,重新写入宿端 AppStorage,同时设置 isRestoredFromContinuation 为 true,通知 UI 主页面执行路由重定向。
- onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
- this.handleRestoreContinuation(want, launchParam);
- }
- onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
- this.handleRestoreContinuation(want, launchParam);
- }
- private handleRestoreContinuation(want: Want, launchParam: AbilityConstant.LaunchParam) {
- // 1. 判断启动原因是否为“流转启动”
- if (launchParam.launchReason === AbilityConstant.LaunchReason.CONTINUATION) {
- console.info("EntryAbility", "Application launched via continuation. Restoring context...");
- const wantParams = want.parameters;
- if (wantParams) {
- // 2. 提取流转上下文
- const targetRoute = wantParams['targetRoute'] as string;
- const editingDraft = wantParams['editingDraft'] as string;
- const cursorOffset = wantParams['cursorOffset'] as number;
- // 3. 将还原的数据再次存入宿端本机的 AppStorage
- AppStorage.setOrCreate('currentRoute', targetRoute);
- AppStorage.setOrCreate('visionLetterDraft', editingDraft);
- AppStorage.setOrCreate('visionInputCursorOffset', cursorOffset);
- // 4. 触发流转状态全局标识,以便 UI 主页面进行路由强行重定向
- AppStorage.setOrCreate('isRestoredFromContinuation', true);
- console.info("EntryAbility", `Successfully restored data draft length: ${editingDraft.length}`);
- }
- }
- }
复制代码
四、UI 侧监听:@Watch 加延时挂载规避闪屏
即使 Ability 层把数据还原到 AppStorage,冷启动时前台 UI 组件也可能尚未完全初始化。此时如果路由立即跳转,容易出现路由加载失败或界面闪烁。因此可在 Index.ets 主入口用 @StorageLink 监听 isRestoredFromContinuation,并通过 @Watch 触发 onRestoreTriggered。触发后延时 100ms,等待主窗口容器与路由栈彻底就绪,再根据 currentRoute 跳到 VisionEditPage,最后重置恢复标识,避免重复跳转。
- @Entry
- @Component
- struct MainIndex {
- @StorageLink('isRestoredFromContinuation') @Watch('onRestoreTriggered') isRestored: boolean = false;
- @StorageLink('currentRoute') currentRoute: string = 'MainTab';
- onRestoreTriggered() {
- if (this.isRestored) {
- // 延时 100ms 等待主窗口容器与路由栈彻底就绪后再发起跳转,规避冷启动瞬间黑屏/闪烁
- setTimeout(() => {
- if (this.currentRoute === 'VisionEditPage') {
- // 发起路由重定向
- this.navigateToEditPage();
- }
- // 重置流转恢复标识
- this.isRestored = false;
- }, 100);
- }
- }
- }
复制代码
通过这层缓冲保护,接续时平板端可以在极度丝滑且没有中间白屏的体验下直接显示手机端编辑界面。
五、实践检查清单
1. 源端只打包必要现场:页面路由、文本草稿、光标偏移量;异常时用 REJECT 拦截。
2. 宿端冷启动和热启动统一处理:onCreate 与 onNewWant 都调用 handleRestoreContinuation。
3. 用 AppStorage 作为 Ability 到 UI 的桥接,避免 UI 未就绪时丢状态。
4. 用 isRestoredFromContinuation 配合 @Watch 触发一次恢复,完成后重置,防止重复跳转。
5. 100ms 延时是等待窗口容器与路由栈就绪的工程处理,不是业务延时。
6. 流转前提是同一华为账号、近场范围,平板 Dock 栏出现流转图标后用户点击触发。
六、总结
通过重写 EntryAbility 的流转生命周期,“轻规划”可以把手机端编辑现场无缝接续到平板端,打破终端物理界限,形成多端无缝工作流。完成分布式数据库多端同步与跨端接续后,下一步原文预告将进入 Device Security Kit AI 防窥保护,涉及人脸识别敏感视线追踪与毛玻璃屏动态遮蔽。 |