鸿蒙Share Kit碰一碰外链传参与Base64解码避坑
在轻规划(AeroPlan)的分享场景里,传统做法是复制长文本或生成大图,再通过微信发送,对方保存或复制后回到应用导入,链路长、跳转多,分享转化率低。HarmonyOS NEXT 的 Share Kit 碰一碰分享将这段流程压缩为一次设备触碰:两台登录不同华为账号的鸿蒙手机靠近后,可唤起系统级快传气泡。AeroPlan 通过自定义 aeroplan:// 外链协议,把九宫格核心数据打包成 Base64 字节流,碰一碰后由接收端拉起并复原规划。下面从环境边界、底层通信、发送端注册、接收端拦截和踩坑排障几个方面展开。一、适用环境与技术边界
系统版本要求 HarmonyOS NEXT Beta(API 12)及以上。分享端与接收端都要有蓝牙与 Wi-Fi 芯片,且蓝牙、Wi-Fi 必须开启;高精度碰一碰物理识别在部分机型上还依赖 UWB 或 NFC 辅助。账号侧支持跨华为账号以及同账号设备之间的近场互传。
数据大小是首要边界:系统级 Want 传递 Scheme URI 的最大安全承载长度建议不超过 4KB(4096 字节)。Base64 编码后的 Scheme 一旦超长,系统调度 Activity 传递 Want 时可能截断,导致反序列化失败。权限方面,调用系统分享面板不需要申请特殊的近场通信危险权限;但接收端应用要被 Scheme 唤起,必须在 module.json5 中正确声明 skills 过滤器,否则系统无法识别外链协议,分享流程会断掉。
二、碰一碰近场通信的职责链路
发送端 A 先做内存数据序列化,把规划转成短文本链接;碰一碰激活后,系统在近场建立临时 P2P 信道,把链接投射给接收端 B;B 捕获 aeroplan:// 后反向冷启动应用并解析入库。底层不是单纯蓝牙传输,而是近场复合网络协议栈,大体分三个阶段。
近场 P2P 发现阶段,A 通过 BLE 以特定服务 UUID 发送加密发现广播;B 在解锁状态下做背景扫描。双方测量 RSSI,若内置 UWB 还会用 ToF 计算厘米级距离。系统判断距离小于阈值且相对速度符合触碰特征时,触发碰一碰确认弹窗。
信道协商阶段,BLE 带宽只有数 Kbps,仅作为控制面信道。确认后,两端通过 Diffie-Hellman 密钥交换生成临时对称密钥,协商建立 Wi-Fi P2P 连接,通常 A 端作为 Group Owner,B 端作为 Client,自动切换信道并建立临时局域网,无需外部 AP。
数据传输阶段,Wi-Fi P2P 建立后,A 端 Share Kit 守护进程通过 TCP Socket 加密发送 SharedData 字节流;B 端接收并校验完整性,关闭临时 P2P 链路,解析 URL 协议,匹配已注册该 Scheme 的应用,以 Want 参数把数据交给目标 Ability。
三、发送端:SharedData 注册与 aeroplan:// 拼接
发送端核心是用 @kit.ShareKit 的 systemShare.SharedData 描述分享内容,再用 systemShare.ShareController 调起系统分享预览。数据准备流程是:用 util.TextEncoder 将规划 JSON 明文编码为 Uint8Array;用 util.Base64Helper 的 encodeToStringSync 转为 Base64 字符串;用 encodeURIComponent 处理规划标题,避免中文或特殊字符破坏 Scheme 解析;拼接 aeroplan://import_plan?title=...&data=...;创建 SharedData,utd 指定为 usid.link,title 展示为轻规划分享标题,description 写提示文案,content 放 shareUrl;通过 ShareController.show(context, ...) 拉起分享,previewMode 使用 DETAIL,selectionMode 使用 SINGLE,保证展示详情且目标单一。原文代码中还通过 try-catch 捕获 BusinessError,打印错误码与错误信息,避免异常导致界面挂起。
四、接收端:冷启动与热启动都要拦截 Want
接收端要在 EntryAbility 中统一处理外链。冷启动时系统创建 Ability 实例,调用 onCreate(want),可直接从参数拿到外链 URI;应用已在后台挂起时,系统复用实例,不再调用 onCreate,而是触发 onNewWant(want)。因此只重写 onCreate 会漏掉热启动分享,甚至展示上一次的旧数据。正确做法是抽一个统一处理方法,在 onCreate 和 onNewWant 中都调用,并在 onNewWant 中把最新 want 传入处理逻辑。
解析流程:判断 want.uri 是否存在且以 aeroplan://import_plan 开头;用 new URL(uriStr) 和 searchParams.get('data') 取 data 参数;用 util.Base64Helper 的 decodeSync 还原 Uint8Array;用 util.TextDecoder('utf-8') 的 decodeWithStream 还原 JSON 字符串;通过 AppStorage.setOrCreate 写入 pendingImportPlanData 和 triggerImportDialog,激活 UI 响应链。这一整段解码必须放在 try-catch 中,防止非法 Base64 或恶意构造数据导致应用崩溃。
五、四个典型踩坑与防御方式
踩坑 1:碰一碰无响应。常见原因是蓝牙或 Wi-Fi 关闭,发现阶段直接阻断;也可能是接收端 module.json5 的 skills 过滤器配置不完整,例如 actions 缺少 ohos.want.action.viewData,或 uris 的 scheme 与发送端不匹配。处理方式是在分享前检测蓝牙、Wi-Fi 状态并引导开启,同时严格校对 skills。原文示例中 actions 包含 ohos.want.action.viewData,entities 包含 entity.system.default 和 entity.system.browsable,uris 配置 scheme 为 aeroplan、host 为 import_plan。
踩坑 2:冷启动正常,热启动拿不到新数据。根因是热启动走 onNewWant,不会重新执行 onCreate。解决方式是统一路由拦截方法,onCreate 和 onNewWant 都调用,必要时备份最新 want。
踩坑 3:Base64 解码非法字符或填充丢失导致 Crash。Base64 中的 +、/、= 在 URL 传输时容易出问题,+ 可能被替换为空格,末尾 = 可能丢失。防御性做法是先做格式预清洗:把空格替换回 +,再按 4 字节对齐补齐 =,最后在 try-catch 中执行 decodeSync,异常时记录原始片段并抛出 Invalid base64 payload。
踩坑 4:超长 Scheme 触发 Want 大小限制。规划矩阵很大时,Base64 后的 Scheme 可能超过 8KB,接收端无响应,底层日志报 Want payload size limit exceeded。原文建议以 4096 字节为安全边界;超限时不要硬塞 Scheme,而是降级为分布式临时同步,只生成 6 位提取码通过 Scheme 传递。这意味着 Scheme 传参更适合轻量数据,复杂规划需要配合分布式存储或数据信箱。
六、小结
通过 Share Kit 碰一碰分享与 aeroplan:// 自定义 Scheme 的编解码链路,轻规划把跨设备分享压缩到一次触碰。工程上真正需要盯紧的是三点:4KB 安全边界、接收端 skills 注册、以及 onCreate/onNewWant 的统一拦截;Base64 在 URL 中的转义和填充补齐则是线上稳定性的关键防线。原文下一篇将进入 Ability Kit 应用接续,在 EntryAbility 全生命周期重写 onContinue。
页:
[1]