一、前言

精准碰一碰是鸿蒙 Share Kit 提供的系统级近场交互能力,区别于传统 NFC 标签碰一碰,它依托鸿蒙分布式软总线,两台鸿蒙设备靠近触碰即可触发应用自定义交互,支持链接、文件、结构化数据的跨设备传递,在资料互传、协同办公、设备联动场景非常好用,也是官方扶持推荐方向。
很多新手在接入时会遇到:碰了没反应、3s 超时失败、接收端无法拉起应用、预览图模糊、冷启动参数丢失等问题。

二、能力原理

精准碰一碰(knockShare)整体流程:

  1. 发送端注册监听:当前页面向系统注册knockShare能力,绑定当前窗口ID,告诉系统:本应用支持碰一碰交换;
  2. 设备触发触碰:两台鸿蒙设备NFC开启,靠近触碰,系统触发回调;
  3. 回调内组装分享数据:在回调函数中构造沉浸式分享卡片、UTD数据,调用share()发起分享;
  4. 接收端接收数据:接收端通过want、onNewWant回调解析传递的数据,完成页面跳转/数据加载;
  5. 异常处理:支持reject()主动拒绝本次碰一碰,给用户友好提示;

对比普通NFC:精准碰一碰不需要实体标签,依靠鸿蒙分布式能力,支持沉浸式大卡片预览,体验更强,适配手机、平板、PC多形态设备协作协同。

三、开发前置准备

  1. DevEco Studio 5.0+,SDK API21
  2. 两台支持 NFC 的鸿蒙设备(真机调试,模拟器无法测试碰一碰)
  3. AGC 后台创建应用,配置 App Linking(如果需要跨应用拉起)
  4. module.json5 配置权限、skills
  5. 依赖:@kit.ShareKit

3.1 module.json5配置

{
  "module": {
    "name": "entry",
    "type": "entry",
    "requestPermissions": [
      {
        "name": "ohos.permission.READ_USER_STORAGE",
        "reason": "读取相册文件用于碰一碰分享",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "inuse"
        }
      }
    ],
    "skills": [
      {
        "entities": ["entity.system.default"],
        "actions": ["ohos.want.action.sendData"],
        "uris": [
          {
            "scheme": "myapp",
            "host": "noteshare",
            "path": "*"
          }
        ]
      }
    ]
  }
}

module.json5配置讲解:

  • ohos.want.action.sendData 是碰一碰数据接收必须注册的 action;
  • uris 配置自定义协议,接收端可以通过该协议被拉起;
  • 存储权限为动态危险权限,代码里还需要动态申请,仅静态声明无效分享图片功能实现解决方案。

四、发送端完整代码(核心ArkTS)

功能:注册碰一碰监听,触碰后分享笔记连接+预览卡片

import { harmonyShare } from '@kit.ShareKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { UIContext } from '@ohos/ui';
import { Want } from '@kit.AbilityKit';

const TAG = 'KnockShareDemo';

@Component
struct KnockSharePage {
  @State uiContext: UIContext | null = null;
  // 监听注册标识,页面销毁时取消监听,防止内存泄漏
  private knockShareOff: (() => void) | null = null;

  aboutToAppear() {
    this.uiContext = this.getUIContext();
    if (!this.uiContext) return;
    const windowId = this.uiContext.getWindowId();

    // 注册精准碰一碰能力
    const registry: harmonyShare.SendCapabilityRegistry = {
      windowId: windowId
    };

    this.knockShareOff = harmonyShare.on('knockShare', registry, async (sharableTarget: harmonyShare.SharableTarget) => {
      hilog.info(0x0000, TAG, '检测到碰一碰事件');
      try {
        // 【重点】提前组装数据,不要在回调里做耗时网络请求!避免3s超时
        const shareData: harmonyShare.ShareData = {
          title: "我的学习笔记",
          description: "鸿蒙精准碰一碰开发笔记",
          thumbnailUri: "file:///data/storage/el2/base/haps/entry/files/preview.jpg", // 沙箱内预览图
          utd: {
            type: "com.myapp.note",
            content: JSON.stringify({
              noteId: 10086,
              title: "精准碰一碰开发",
              link: "myapp://noteshare/detail?noteId=10086"
            })
          }
        };

        // 发起分享
        await sharableTarget.share(shareData);
        hilog.info(0x0000, TAG, '分享发起成功');
      } catch (err) {
        hilog.error(0x0000, TAG, '分享失败 %{public}s', JSON.stringify(err));
        // 主动拒绝本次碰一碰,给系统反馈
        sharableTarget.reject("数据准备失败");
      }
    })
  }

  // 页面销毁,取消监听,非常重要
  aboutToDisappear() {
    if (this.knockShareOff) {
      this.knockShareOff();
      this.knockShareOff = null;
    }
  }

  build() {
    Column() {
      Text("精准碰一碰发送端")
        .fontSize(22)
        .margin({ bottom: 10 })
      Text("打开本页面,两台鸿蒙手机触碰,即可分享笔记")
        .fontSize(14)
        .fontColor("#666")
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

代码讲解:

  1. harmonyShare.on('knockShare') 注册碰一碰回调,返回的函数用于注销监听,页面销毁必须调用,否则多次进入页面会重复注册;
  2. thumbnailUri 优先使用沙箱文件 URI;不要直接传 PixelMap,旧参数 thumbnail 有 32KB 大小限制,图片会模糊,这是高频坑----(碰一碰视频链接分享开发实践解析);
  3. 禁止在回调内部做网络请求、大文件读取这类耗时操作,很容易触发 3 秒超时,数据提前预加载;
  4. sharableTarget.reject() 用于异常场景终止本次碰一碰交互,提升用户体验。

五、接收端代码:解析碰一碰传递的数据

接收端分两种场景:应用冷启动、应用已经在后台运行(onNewWant)

// EntryAbility.ets
import { UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

export default class EntryAbility extends UIAbility {
  onNewWant(want: Want) {
    // 应用后台运行,碰一碰拉起触发这里
    hilog.info(0x0000, 'Receiver', 'onNewWant, want: %{public}s', JSON.stringify(want));
    this.parseKnockWant(want);
  }

  onCreate() {
    hilog.info(0x0000, 'Receiver', 'Ability onCreate');
  }

  onWant(want: Want) {
    // 应用冷启动,碰一碰拉起
    this.parseKnockWant(want);
  }

  private parseKnockWant(want: Want) {
    const uri = want.uri;
    if (!uri) return;
    // 解析自定义协议 myapp://noteshare/detail?noteId=10086
    hilog.info(0x0000, 'Receiver', '收到碰一碰传递链接:%{public}s', uri);
    // 路由跳转笔记详情页
    this.context.router.pushUrl({ url: `pages/NoteDetail?uri=${uri}` })
  }
}

代码讲解:

  • onNewWant 是后台驻留时的入口,很多开发者只写 onCreate,后台碰一碰无法响应;
  • 解析 uri 参数后,使用 router 跳转对应业务页面;
  • 如果接收方没有安装 App,可以在 AGC 配置 App Linking,跳转应用市场。

六、核心隐蔽代码坑

这部分属于多次踩坑!

坑 1:碰一碰回调触发,但是 share 报错,提示超时

  • 现象:设备碰了,日志打印进入回调,但是分享失败。
  • 原因:回调内同步 / 异步耗时过长,超过 3s 时限。
  • 方案:所有分享数据、缩略图提前预加载,回调内只调用 share (),不做 IO、网络操作。

坑 2:预览卡片图片模糊

  • 现象:分享卡片缩略图很糊。
  • 原因:使用了thumbnail(二进制缩略图字段,上限 32KB)
  • 方案:改用thumbnailUri,把图片保存到应用沙箱,传入文件 URI。

坑 3:接收端碰一碰无法拉起应用
排查顺序:

  1. module.json5 skills 是否配置ohos.want.action.sendData;
  2. 签名:不能使用自动调试签名,必须手动签名;
  3. 协议 uri 是否匹配,大小写严格一致;
  4. 测试设备是否登录华为账号、NFC 开关打开。

坑 4:多次进入页面,碰一碰多次回调

  • 原因:页面重复注册监听,离开页面没有调用注销函数。
  • 方案:aboutToDisappear 执行 off 注销。

坑 5:模拟器无法测试碰一碰
说明:精准碰一碰依赖 NFC 硬件和分布式能力,必须两台鸿蒙真机(说明:一部华为pura80(新),一部华为Mate70(旧))。

七、测试流程

  1. 两台鸿蒙真机,都开启 NFC;
  2. 两台设备安装同一个应用;
  3. 发送端打开 KnockSharePage 页面;
  4. 两台手机 NFC 区域互相触碰;
  5. 系统弹出沉浸式分享卡片,接收端自动拉起,跳转笔记详情页;
  6. 验证异常场景:网络差、文件不存在,reject 提示正常。

碰一碰测试流程总览:

数据正常

异常:文件不存在/数据错误

应用未启动(冷启动)

应用后台运行

准备阶段

两台鸿蒙真机,开启NFC

两台设备安装同一套鸿蒙应用

发送端操作

发送端打开 KnockSharePage 页面

页面aboutToAppear:注册knockShare碰一碰监听

预加载分享数据、预览图,避免3s超时

设备触碰触发

两台手机NFC区域靠近触碰

系统检测碰一碰事件,触发回调

回调内校验

组装ShareData,调用share

调用reject,终止分享,输出异常日志

系统弹出沉浸式分享卡片

接收端响应

应用状态判断

触发onWant,解析协议uri

触发onNewWant,解析协议uri

路由跳转笔记详情页

流程结束,提示用户分享失败

流程结束,分享成功

页面退出:aboutToDisappear,注销碰一碰监听,防止重复注册

流程图说明:

  1. 预加载是核心:数据、缩略图提前准备,回调中只做分享调用,规避官方 3s 超时限制;
  2. 生命周期成对管理:页面出现注册监听,页面销毁注销监听,防止重复回调;
  3. 接收端双分支:区分冷启动 onWant 和后台唤起 onNewWant,很多开发者只处理其中一个,导致 bug;
  4. 异常分支独立:文件缺失、数据异常时调用 reject 主动拒绝碰一碰,给系统明确反馈,体验更好。

八、扩展方向

准碰一碰能力还可以延伸这些玩法:

  1. 平板 + PC 协同:碰一碰,在文档光标位置插入图片(26.0.0 版本支持获取触碰坐标)鸿蒙系统“碰一碰”功能详解与开发适配指南;
  2. 学习类 App:碰一碰交换学习卡片、作业、思维导图;
  3. 折叠屏适配:在折叠态 / 展开态下,修改碰一碰分享卡片布局;
  4. 结合文搜图、图像超分:碰一碰传递图片后,接收端自动超分。

九、结语

  1. 精准碰一碰是鸿蒙分布式协同非常有特色的能力,上手门槛不高,但约束细节很多,3 秒时限、监听生命周期、签名配置、缩略图字段,都是新手最容易踩的卡点。
  2. 本文 Demo 基于 API21 原生 Share Kit,没有引入第三方框架,可以直接把代码集成到自己的学习、办公类鸿蒙项目中,快速实现跨设备一碰协同。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐