前言
会务组提的需求:圆桌会议上大家各自拍照片、记笔记,散会时把自己那份"碰一下"递给对面的嘉宾,不用加微信、不用传群、不用点名选接收人。
这就是 Share Kit 的碰一碰分享。API 只有三行:注册回调、回调里给数据、系统把内容送过去。
我带你把发送侧完整写一遍。但请先记住这篇最重要的一句话:碰一碰的注册接口"注册即成功",它不会告诉你这台设备根本没有 NFC。 我在一台平板上实测,四次调用全部无异常,回调触发次数是 0。所以这篇的后半段会告诉你,哪些部分必须两台设备、两次真人才测得出来。
第 1 步:先探能力,别先写代码
新建工程后第一件事,把这几项系统能力打出来:
const share: boolean = canIUse('SystemCapability.Collaboration.HarmonyShare');
const sysShare: boolean = canIUse('SystemCapability.Collaboration.SystemShare');
const nfc: boolean = canIUse('SystemCapability.Communication.NFC.Core');
const collab: boolean = canIUse('SystemCapability.Application.DeviceCollaboration');MatePad Pro(HarmonyOS 7 / API 26)的结果:
HarmonyShare=true SystemShare=true NFC.Core=false DeviceCollaboration=false前两个 true 说明接口在,后两个 false 说明这台机器碰不了。
这一步为什么关键:SystemCapability.Communication.NFC.Core 为 false 时,后面所有注册调用依然全部成功。你如果只看"有没有抛异常"来判断功能是否可用,一定会写出一个静默无效的发布版本。
正确的自检写法是:把 NFC.Core 当成开关,为 false 就在界面上直接显示"本设备不支持碰一碰",而不是等用户去碰。
第 2 步:注册发送回调
private onKnock: (target: harmonyShare.SharableTarget) => void =
(target: harmonyShare.SharableTarget) => {
// 系统检测到一次碰一碰,把 target 交给你
target.share(this.buildData());
};
aboutToAppear(): void {
harmonyShare.on('knockShare', this.onKnock);
}
aboutToDisappear(): void {
harmonyShare.off('knockShare', this.onKnock);
}三个必须注意的点:
- 回调引用要存成成员变量。
off要传同一个函数引用,写成匿名函数就注销不掉,页面反复进出会叠加回调。 - **注册时机放
aboutToAppear,注销放aboutToDisappear。**碰一碰是前台行为,页面已经销毁还挂着回调,会在不该出现的时候把这一页的数据分享出去。 on还有第二个重载on('knockShare', capability: SendCapabilityRegistry, callback),带窗口注册表,用于多窗口场景精确指定是哪个窗口发起分享(26.0.0 起电脑设备支持精准碰一碰)。单窗口应用可以先不碰它。

第 3 步:在回调里给数据
SharableTarget 上有四个出口,用错会导致对端表现很奇怪:
| 方法 | 什么时候用 |
|---|---|
share(data: systemShare.SharedData) |
正常分享 |
reject(error: SharableErrorCode) |
当前状态下不该分享(比如没选中照片),让系统给出提示 |
clarifyNonShare(info) |
明确告诉系统这次不算分享,静默取消 |
updateShareData(info) |
内容变了,更新将要分享的数据 |
getInfo() |
拿对端设备信息,用于埋点 |
SharedData 的构造里 utd 是必填的(Uniform Type Descriptor),文本用 'text/plain':
new systemShare.SharedData({
utd: 'text/plain',
content: '议题:端侧模型上线节奏\n结论:先灰度 10%,下周三给数据\n负责人:张三',
title: '参会笔记 · 端侧模型评审',
description: `由「碰记」在 19:07 导出`
});图片/文件类内容要传 uri,并且这个 uri 必须是应用能访问到的沙箱路径或授权过的 uri——直接传相册 uri 过去,对端拿不到文件,表现就是"碰了但对方什么都没收到"。这是官方 FAQ 里"暂无可用打开方式"的常见成因之一。
第 4 步:接收侧注册
要让本机能收,得注册 dataReceive,并声明能接哪些类型:
const reg: harmonyShare.RecvCapabilityRegistry = {
windowId: 0,
capabilities: [{ utd: 'text/plain', maxSupportedCount: 4 }]
};
harmonyShare.on('dataReceive', reg, (t: harmonyShare.ReceivableTarget) => {
// t.getInfo() 里拿到内容
});这里有个坑我踩给你看:上面这段 windowId 我故意传了 0(明显不是真实窗口 id),结果照样返回"注册成功",不抛异常:
on(dataReceive) 注册成功(windowId 传了 0)也就是说参数不做校验。真实窗口 id 要从 window 模块拿(windowClass.windowProperties.id 或 getWindowProperties().id)。传错的表现是"注册成功但永远收不到",和没注册完全一样,排查成本极高。

第 5 步:把没测到的部分说清楚
我这轮只连了一台设备,所以以下这些没有数据,不编:
- 真实对碰时
onKnock到底什么时候被调、getInfo()里有哪些字段; target.share()之后对端的落地形态(是通知、是打开应用、还是进分享面板);- 未注册时碰一碰的系统提示文案;
- 一次碰多张图片(
maxSupportedCount的实际生效上限); - 两台设备登录不同华为账号时的权限表现。
这些必须两台 NFC 设备 + 真人对碰才能验。写教程到这一步,诚实的做法就是把清单交出去,而不是把"应该可以"写成"已验证"。
实测数据
单台 MatePad Pro,按顺序点五个动作:
| 动作 | 结果 | 是否抛异常 |
|---|---|---|
| 探测四项 syscap | HarmonyShare=true / SystemShare=true / NFC.Core=false / DeviceCollaboration=false | 否 |
on('knockShare') |
注册成功 | 否 |
再 on('knockShare') 一次 |
也成功,无提示 | 否 |
on('dataReceive', {windowId:0,...}) |
注册成功 | 否 |
off('knockShare') |
完成 | 否 |
重新 on('knockShare') |
注册成功 | 否 |
| 回调实际触发次数 | 0 | — |
结论一句话:六个调用全绿,功能一次都没生效。 这就是"靠返回值做自检"的失败模式。
上线前请做完这四件事
- 界面上显式区分"接口可用"和"设备支持":
NFC.Core=false时直接禁用碰一碰入口。 windowId用真实值,并在注册后把它打一行日志,出问题时第一眼就能看到。- 分享出去的内容做本地留痕(谁、什么时候、碰给了哪台),否则用户报"我没收到"时你无从对账。
- 两台真机、两个账号、正反向各碰一次,作为发布卡点,而不是开发自测项。
总结
碰一碰适合"临时、一次性、身边人"的内容交接:会议笔记、现场照片、展台资料、同学之间传一道题。它的价值在于省掉"找联系人—发出去—对方点开"这一串,所以内容要小、要即时。
不适合大文件、需要留痕审计的场景,也不适合设备形态里没有 NFC 的机器(部分平板就没有)。后者不是降级能解决的,只能换交互。
💡 一句话:
harmonyShare.on()在没有 NFC 的设备上也会返回成功——判断能不能碰,只能靠canIUse('SystemCapability.Communication.NFC.Core'),不能靠注册有没有报错。
参考文献
- 碰一碰文件分享(最佳实践):https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-application-knock-file-share
- 碰一碰链接分享(最佳实践):https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-application-knock-video-share
- harmonyShare(华为分享)API 参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/share-harmony-share
- Share Kit 简介:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/share-introduction