碰一碰功能简介

碰一碰是鸿蒙系统(HarmonyOS)提供的一种超近场分享能力。用户通过将两台设备顶部轻轻触碰(手机与手机)或将手机顶部轻触屏幕(手机与电脑/平板),即可快速建立连接并分享内容。该功能由 Share Kit(分享服务)提供支持,目前支持手机与手机、手机与 PC/2in1 设备之间的碰一碰分享;从 6.1.0(23) 版本开始,新增支持手机与 Tablet 设备之间的碰一碰分享。

适用场景:碰一碰分享适用于设备间的快速分享,支持分享的内容包括图片、视频、网络链接、联系人、链接等。

碰一碰分享界面设计

设备碰一碰成功建立连接后,会形成分享界面。分享界面由以下 4 大部分组成:

  1. 虫洞区:碰后设备间若成功建立连接,顶部出现虫洞,用于飞出或飞入卡片。不支持应用自定义。
  2. 卡片区:用于分享内容展示,提供 5 类模板,生态应用根据分享内容选择不同模板。
  3. 信息展示区:用于展示分享时对方的设备信息,包括华为账号头像以及设备名称。在 1 碰多的场景中会出现头像叠加。不支持应用自定义。
  4. 操作区:发送端和接收端分别为引导字符和按钮,展示交互方式和操作意图。不支持应用自定义。

说明:当前名片类模板仅对系统联系人应用开放。

卡片模板

根据不同的分享内容和业务诉求,Share Kit 提供 5 类卡片模板,应用可根据不同需求选择不同模板。

图片、视频类卡片模板

  • 适用场景:分享内容为图片或视频。
  • 应用接入:应用需传入预览图片或者视频。
  • 卡片详情:根据原图片比例进行自适应显示,支持比例范围为 4:1 ~ 1:4 ,超出进行图片居中裁剪。

文件类卡片模板

  • 适用场景:分享内容为文件、WIFI 或者个人热点。
  • 应用接入:应用需传入主副文本。文件类主文本为文件名称及类型,辅助文本为文件大小。
  • 卡片详情:卡片比例固定为 4:3 。

链接类卡片模板

  • 适用场景:分享内容为链接,例如音乐链接、视频链接、商品链接等等。
  • 应用接入:应用需传入主副文本、预览图以及应用图标。若分享类型为名片,则还需传入用户头像。
  • 卡片详情:最佳预览图比例为 4:3、1:1、16:9,应用请尽量传入上述比例预览图。超出 4:3 ~ 16:9 的比例图片居中裁剪。

链接类模板可分为内容分享名片分享两类,应用可根据分享内容进行匹配。应用传入的预览图尽量保持在 4:3、1:1、16:9 三种比例,以此可保障画面不被裁剪;同时尽量选取主体明确、比例合适、底部无重要信息露出的图片,以获得最佳显示效果。

其他卡片模板

  • 适用场景:系统分享面板碰一碰 & 无预览图特殊场景。
  • 应用接入:应用需传入主副文本,以及应用图标。
  • 卡片详情:无预览图时,展示当前卡片样式。

手机与手机碰一碰分享开发适配

场景介绍与业务流程

场景介绍:宿主应用进入一个可以分享的界面,比如打开或者选中的一个文件、一条备忘录、一个联系人详情,或个人热点/Wi-Fi 等。宿主应用可以分享多个内容,如选中的多张图片等。

业务流程

  1. 宿主应用注册碰一碰分享事件,并与亮屏且解锁的对端设备碰一碰。
  2. 宿主应用发现设备,调用碰一碰分享事件回调,在回调事件中构造分享数据并发送。
  3. 目标设备接收并处理分享数据。
  4. 宿主应用解除注册碰一碰分享事件。

使用约束与环境要求

使用约束

  • 手机应用发起碰一碰分享时,双端设备需要在亮屏、且解锁的状态下并且都已开启华为分享服务(系统默认开启),设备顶部轻碰即可触发。
  • 如果用户已手动关闭华为分享服务开关,轻碰事件触发时,用户会接收到系统通知提示开启。
  • 任意一端设备不支持碰一碰能力时,轻碰无任何响应。
  • 宿主应用无法获得分享结果,Share Kit 会通过系统通知消息告知用户对端接收或拒绝。

环境要求

  • 支持的手机系统:HarmonyOS NEXT Release 及以上版本,可使用 canIUse 判断系统能力是否支持:
if (canIUse('SystemCapability.Collaboration.HarmonyShare')) {
  // 支持一碰分享的能力.
}
  • 集成开发环境:DevEco Studio NEXT Beta1 及以上版本。

注册碰一碰事件与发送分享数据

当用户进入支持碰一碰分享的界面或场景时,应通过 harmonyShare.on('knockShare', ...) 注册碰一碰分享事件。注册时需要传入 SendCapabilityRegistry,其中包含 windowId 等信息。在回调中构造 SharedData 并调用 sharableTarget.share(shareData) 发送数据。

示例代码(基础注册与发送):

import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { fileUri } from '@kit.CoreFileKit';

@Component
export default struct Index {
  aboutToAppear(): void {
    let capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
      windowId: 999, // 此值仅为示例 实际使用时请替换正确的windowId
    }
    harmonyShare.on('knockShare', capabilityRegistry, (sharableTarget: harmonyShare.SharableTarget) => {
      let uiContext: UIContext = this.getUIContext();
      let contextFaker: Context = uiContext.getHostContext() as Context;
      let filePath = contextFaker.filesDir + '/exampleKnock1.jpg'; // 仅为示例 请替换正确的文件路径
      let shareData: systemShare.SharedData = new systemShare.SharedData({
        utd: utd.UniformDataType.HYPERLINK,
        content: 'https://sharekitdemo.drcn.agconnect.link/ZB3p',
        thumbnailUri: fileUri.getUriFromPath(filePath),
        title: '碰一碰分享卡片标题',
        description: '碰一碰分享卡片描述'
      });
      sharableTarget.share(shareData);
    });
  }

  aboutToDisappear(): void {
    let capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
      windowId: 999, // 此值仅为示例 实际使用时请替换正确的windowId
    }
    harmonyShare.off('knockShare', capabilityRegistry);
  }

  build() {
  }
}

设置分享预览

接入碰一碰分享时,需根据不同的分享数据类型,适配相应的卡片模板。Share Kit 支持三种卡片模板供手机发起碰一碰分享时选择:

纯图片布局

  • 说明:只包括预览图。当分享数据为文件、图片等无需添加标题及描述的场景,推荐使用。
  • 使用方法:构造分享数据时,仅传递预览图(thumbnailUri)字段。
  • 布局要求:预览图支持最小宽高比 1:4,超出部分将被裁剪。

沉浸式大卡布局

  • 说明:包括预览图、标题、描述、应用图标。当分享数据为链接类型,需要向用户传递链接内容时推荐使用。
  • 使用方法:需同时满足两个条件:
    1. 构造分享数据时,同时传入标题(title)、描述(description)和预览图(thumbnailUri)字段。
    2. 预览图宽高比小于 1:1。
  • 布局要求
    • 预览图:支持最小宽高比 1:4,超出部分将被裁剪。
    • 标题:最大可显示 2 行,超过用省略号代替。建议应用自行控制字数约 20 个中文左右。
    • 描述:仅可显示 1 行,超过用省略号代替。
    • 应用图标:无需配置,系统默认获取应用图标显示在卡片底部。

白卡上下布局

  • 说明:包括预览图、标题、描述、应用图标。当分享数据为链接类型,需要向用户传递链接内容时推荐使用。
  • 使用方法:需同时满足两个条件:
    1. 构造分享数据时,同时传入标题(title)、描述(description)和预览图(thumbnailUri)字段。
    2. 预览图宽高比大于 1:1。
  • 布局要求
    • 预览图:仅显示在卡片上方,不会铺满整个卡片。
    • 标题:最大可显示 2 行,超过用省略号代替;建议控制约 20 个中文。
    • 描述:仅可显示 1 行,超过用省略号代替。
    • 应用图标:无需配置,系统默认获取应用图标显示在卡片底部。

设置合适的预览图

预览图的质量直接影响碰一碰卡片的显示效果。建议按照以下推荐设置:

预览图来源 推荐比例 推荐分辨率(px) 推荐大小(KB)
应用创作的海报 3:4 最小 600 * 800,最大 3000 * 4000 512KB,若超过会被压缩
用户上传的图片 不限制 最小不限制,最大 3000 * 4000 512KB,若超过会被压缩

使用预览图更新能力

当应用使用云端存储的图片作为预览图时,碰一碰分享的回调触发时可能无法及时下载到本地而导致超时失败。Share Kit 提供预览图延迟更新能力:

  • 在接到碰一碰事件回调时,可仅发送分享的核心数据内容,建立连接;Share Kit 会提供默认预览图用于卡片展示。
  • 待云端图片下载完成后,调用 sharableTarget.updateShareData 接口更新预览图信息。

示例代码

import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { fileUri } from '@kit.CoreFileKit';

@Component
export default struct Index {
  aboutToAppear(): void {
    let capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
      windowId: 999 // 此值仅为示例 实际使用时请替换正确的windowId
    }
    harmonyShare.on('knockShare', capabilityRegistry, (sharableTarget: harmonyShare.SharableTarget) => {
      let shareData: systemShare.SharedData = new systemShare.SharedData({
        utd: utd.UniformDataType.HYPERLINK,
        content: 'https://sharekitdemo.drcn.agconnect.link/ZB3p',
        title: '碰一碰分享卡片标题',
        description: '碰一碰分享卡片描述'
      });
      sharableTarget.share(shareData);

      setTimeout(() => {
        let uiContext: UIContext = this.getUIContext();
        let contextFaker: Context = uiContext.getHostContext() as Context;
        let filePath = contextFaker.filesDir + '/exampleKnock1.jpg';
        sharableTarget.updateShareData({
          thumbnailUri: fileUri.getUriFromPath(filePath)
        });
      }, 5000);
    });
  }

  aboutToDisappear(): void {
    let capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
      windowId: 999
    }
    harmonyShare.off('knockShare', capabilityRegistry);
  }

  build() {
  }
}

安全策略

在 HarmonyOS NEXT 5.0.0.123 SP16 及以上版本,碰一碰分享增加了对端华为账号或设备标识,帮助用户识别分享发送端/接收端的身份。具体规则如下:

设备 对端已登录华为账号 对端未登录华为账号
碰一碰发送端 展示接收端华为账号昵称和头像。 展示接收端设备信息。
碰一碰接收端 展示发送端华为账号昵称和头像(若发送端为旧版本则不会展示)。 展示发送端设备信息(若发送端为旧版本则不会展示)。

发送分享数据方式

通过链接形式指定应用跳转,通常有两种方式:App LinkingDeep Linking。指定应用跳转时,utd 类型需配置为 "general.hyperlink",确保 Share Kit 以正确的方式处理链接。

App Linking

  • 使用 App Linking 进行跳转时,无论应用是否已安装,用户都可以访问到链接对应的内容。
  • 结合 App Linking Kit(应用链接服务)能力,在指定应用未安装时,可实现直达应用市场等能力。
  • 当应用已安装时,App Linking 可直接拉起应用;当应用未安装时,默认通过系统浏览器打开链接对应网页,也可通过直达应用市场能力跳转应用市场。
  • 配合延迟链接能力,即便触发碰一碰分享时应用未安装,待下载启动后仍能获取之前分享的链接,提升链接转换率。

示例代码(App Linking 方式):

import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { harmonyShare, systemShare } from '@kit.ShareKit';
import { fileUri } from '@kit.CoreFileKit';

@Component
export struct HarmonyShareScenes {
  onPageHide(): void {
    let uiContext: UIContext = this.getUIContext();
    let context: Context = uiContext.getHostContext() as Context;
    context.eventHub.emit('onBackGround');
  }

  aboutToAppear(): void {
    this.immersiveListening();
    let uiContext: UIContext = this.getUIContext();
    let context: Context = uiContext.getHostContext() as Context;
    context.eventHub.on('onBackGround', this.onBackGround);
  }

  aboutToDisappear(): void {
    this.immersiveDisablingListening();
    let uiContext: UIContext = this.getUIContext();
    let context: Context = uiContext.getHostContext() as Context;
    context.eventHub.off('onBackGround', this.onBackGround);
  }

  build() { }

  private onBackGround = () => {
    this.immersiveDisablingListening();
  }

  private immersiveCallback = (sharableTarget: harmonyShare.SharableTarget) => {
    let uiContext: UIContext = this.getUIContext();
    let contextFaker: Context = uiContext.getHostContext() as Context;
    let filePath = contextFaker.filesDir + '/exampleKnock1.jpg';
    let shareData: systemShare.SharedData = new systemShare.SharedData({
      utd: utd.UniformDataType.HYPERLINK,
      content: 'https://sharekitdemo.drcn.agconnect.link/ZB3p',
      thumbnailUri: fileUri.getUriFromPath(filePath),
      title: '碰一碰分享卡片标题',
      description: '碰一碰分享卡片描述'
    });
    sharableTarget.share(shareData);
  }

  private immersiveListening() {
    harmonyShare.on('knockShare', this.immersiveCallback);
  }

  private immersiveDisablingListening() {
    harmonyShare.off('knockShare', this.immersiveCallback);
  }
}

Deep Linking

使用 Deep Linking 进行跳转时,系统仅会在本地已安装的应用中寻找到符合条件的应用。未找到时将弹出提示暂无可用打开方式。

异常场景终止分享

在碰一碰事件回调触发时,可能由于某些原因无法发起分享,此时需及时终止分享,避免用户长时间等待。根据实际场景,有以下处理方式:

当前界面无可分享内容

从 6.0.2(22) 版本开始,当前界面的内容不支持碰一碰分享时,开发者可通过 sharableTarget.clarifyNonShare() 终止本次分享,并引导用户前往可分享界面再次尝试。

示例代码

import { harmonyShare } from '@kit.ShareKit';

aboutToAppear(): void {
  harmonyShare.on('knockShare', (sharableTarget: harmonyShare.SharableTarget) => {
    sharableTarget.clarifyNonShare({ message: '请在支持碰一碰分享的界面再试' });
  });
}

分享内容下载失败等其他异常场景

从 5.0.3(15) 版本开始,由于网络或者业务原因无法发起分享时,开发者可通过 sharableTarget.reject() 终止本次分享,并提示用户终止的原因。

示例代码

import { harmonyShare } from '@kit.ShareKit';

aboutToAppear(): void {
  harmonyShare.on('knockShare', (sharableTarget: harmonyShare.SharableTarget) => {
    sharableTarget.reject(harmonyShare.SharableErrorCode.DOWNLOAD_ERROR);
  });
}

邀请组队场景

在组队房间邀请界面,可以通过碰一碰分享邀请好友加入组队房间。

注册单向分享能力

若双方都同时在组队房间内互相邀请,无法相互加入对方的组队房间。针对此场景,Share Kit 提供单向仅发送能力(sendOnly 属性)。若碰一碰的双方都设置单向仅发送,则终止本次分享并提示用户“请任意一方退出当前应用后再试”;反之,均可分享成功。

示例代码

import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { fileUri } from '@kit.CoreFileKit';

@Component
export default struct Index {
  aboutToAppear(): void {
    let capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
      windowId: 999,
      sendOnly: true // 声明仅支持单向发送
    }
    harmonyShare.on('knockShare', capabilityRegistry, (sharableTarget: harmonyShare.SharableTarget) => {
      let uiContext: UIContext = this.getUIContext();
      let contextFaker: Context = uiContext.getHostContext() as Context;
      let filePath = contextFaker.filesDir + '/exampleKnock1.jpg';
      let shareData: systemShare.SharedData = new systemShare.SharedData({
        utd: utd.UniformDataType.HYPERLINK,
        content: 'https://sharekitdemo.drcn.agconnect.link/ZB3p',
        thumbnailUri: fileUri.getUriFromPath(filePath),
        title: '碰一碰分享卡片标题',
        description: '碰一碰分享卡片描述'
      });
      sharableTarget.share(shareData);
    });
  }

  aboutToDisappear(): void {
    let capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
      windowId: 999
    }
    harmonyShare.off('knockShare', capabilityRegistry);
  }

  build() { }
}

设置组队邀请预览

预览图设置参考“设置分享预览”部分。

处理组队链接

当目标应用被分享拉起时,可以通过 onCreateonNewWant 回调中获取传入的 want 参数。其中 want.uri 字段为邀请组队的链接,通过链接上携带的参数信息,处理组队邀请的业务逻辑。

示例代码

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';

export default class EntryAbility extends UIAbility {
  async onWindowStageCreate(windowStage: window.WindowStage): Promise<void> {
    try {
      windowStage.loadContent('pages/Index');
    } catch (error) {
      console.error(`onWindowStageCreate error. Code: ${error?.code}, message: ${error?.message}`);
    }
  }

  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    console.info('EntryAbility onCreate invoked. uri: ', want.uri);
    // to do things.
  }

  onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    console.info('EntryAbility onNewWant invoked. uri: ', want.uri);
    // to do things.
  }
}

手机与 PC/2in1(及 Tablet)碰一碰分享开发适配

场景介绍与业务流程

Share Kit 支持 Phone 和 PC/2in1 之间的碰一碰分享。利用 PC/2in1 设备的屏幕感知能力,识别 Phone 轻碰屏幕的动作及位置,实现 PC/2in1 窗口级的交互。从 6.1.0(23) 版本开始,支持 Phone 与 Tablet 设备之间的碰一碰分享。

业务流程

  • PC/2in1 设备作为数据接收端:手机轻碰 PC/2in1 屏幕,PC/2in1 接收数据。
  • PC/2in1 设备作为数据发送端:PC/2in1 窗口内容通过碰一碰发送至手机。

双向分享限制

从 6.0.0(20) Beta5 版本开始,手机与 PC/2in1 设备之间不支持双向分享。遵循以下机制:

  • 当手机前台有可分享内容时,无论 PC/2in1 设备前台窗口是否有可分享内容,优先将手机作为发送端,PC/2in1 设备作为接收端。
  • 当手机前台无可分享内容且 PC/2in1 设备前台窗口有可分享内容时,PC/2in1 设备作为发送端,手机作为接收端。
  • 当手机前台和 PC/2in1 设备前台窗口均无可分享内容时,遵循无内容分享逻辑。

对于 6.0.0(20) Beta3 及之前的版本,当手机前台和 PC/2in1 设备前台窗口均有可分享内容时,支持双向分享(发送分享内容的同时也可接收到分享内容)。

使用约束

  • 手机与 PC/2in1 设备间碰一碰分享需登录相同的华为账号。
  • 仅支持直板手机或折叠手机直板态与 PC/2in1 屏幕碰一碰分享。
  • 轻碰屏幕交互约束
    • 手机与 PC/2in1 屏幕俯视夹角应 ≤5°。
    • 手机与 PC/2in1 屏幕侧视夹角应 >35°。
    • 手机与 PC/2in1 屏幕正视夹角应 ≤25°。
    • 手机不能超出 PC/2in1 设备屏幕。
    • 支持官方手机保护壳,不支持过厚的手机外壳。

环境要求

  • 支持的 PC/2in1 系统:HarmonyOS 6.0.0 Beta1 及以上版本。
  • 集成开发环境:DevEco Studio 6.0.0 Beta1 及以上版本。

分享内容直达应用界面(沙箱接收)

从 6.0.0(20) 版本开始,沙箱接收能力支持 PC/2in1 设备;从 6.1.0(23) 版本开始,新增支持 Tablet 设备。支持手机轻贴屏幕即可将单/多文件快速传输至 PC/2in1 或 Tablet 设备应用沙箱,传输完成后通知目标应用接收文件列表,实现无缝预览与编辑。

约束:沙箱接收仅支持文件类型的数据,应用需指定支持接收的文件类型和最大数量。若类型不匹配,则跳过已注册的沙箱接口能力,采用华为分享默认逻辑接收文件数据;若数量不匹配,则通过系统弹窗提示用户异常。

开发步骤

  1. 导入相关模块
import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { common } from '@kit.AbilityKit';
  1. 注册沙箱接收事件(在可接收数据的窗口出现时):
aboutToAppear(): void {
  let capabilityRegistry: harmonyShare.RecvCapabilityRegistry = {
    windowId: 999, // 此值仅为示例
    capabilities: [{
      utd: utd.UniformDataType.IMAGE,
      maxSupportedCount: 1
    }]
  }
  harmonyShare.on('dataReceive', capabilityRegistry, (receivableTarget: harmonyShare.ReceivableTarget) => {
    let uiContext: UIContext = this.getUIContext();
    let context = uiContext.getHostContext() as common.UIAbilityContext;
    receivableTarget.receive(context.filesDir, {
      onDataReceived: (sharedData: systemShare.SharedData) => {
        let sharedRecords = sharedData.getRecords();
        sharedRecords.forEach((record: systemShare.SharedRecord) => {
          // 处理分享数据
        });
      },
      onResult(resultCode: harmonyShare.ShareResultCode) {
        if (resultCode === harmonyShare.ShareResultCode.SHARE_SUCCESS) {
          // To do things.
        }
      }
    });
  });
}
  1. 取消沙箱接收事件(在窗口关闭时):
aboutToDisappear(): void {
  let capabilityRegistry: harmonyShare.RecvCapabilityRegistry = {
    windowId: 999,
    capabilities: [{
      utd: utd.UniformDataType.IMAGE,
      maxSupportedCount: 1
    }]
  }
  harmonyShare.off('dataReceive', capabilityRegistry);
}

拒绝本次沙箱接收

当本次沙箱接收回调触发时,如果应用因为业务实现需要拒绝本次接收,可使用 ReceivableTarget.reject() 方法。

示例代码

import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { harmonyShare } from '@kit.ShareKit';

@Component
export default struct Index {
  aboutToAppear(): void {
    let capabilityRegistry: harmonyShare.RecvCapabilityRegistry = {
      windowId: 999,
      capabilities: [{
        utd: utd.UniformDataType.IMAGE,
        maxSupportedCount: 1
      }]
    }
    harmonyShare.on('dataReceive', capabilityRegistry, (receivableTarget: harmonyShare.ReceivableTarget) => {
      receivableTarget.reject(harmonyShare.ReceivableErrorCode.NO_RECEIVABLE_ERROR);
    });
  }

  aboutToDisappear(): void {
    let capabilityRegistry: harmonyShare.RecvCapabilityRegistry = {
      windowId: 999,
      capabilities: [{
        utd: utd.UniformDataType.IMAGE,
        maxSupportedCount: 1
      }]
    }
    harmonyShare.off('dataReceive', capabilityRegistry);
  }

  build() { }
}

获取轻碰坐标

从 26.0.0 版本开始,手机与 PC/2in1、手机与 Tablet 设备触发轻碰事件时,在 PC/2in1 或 Tablet 设备侧可从回调事件中获取轻碰的位置(基于屏幕左上角为初始点的坐标信息)。通过轻碰的位置不同,可实现不同的业务逻辑,例如向文档指定位置插入图片,或者获取窗口中指定的图片等。

示例代码(包含发送端和接收端获取坐标):

import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { harmonyShare, systemShare } from '@kit.ShareKit';
import { fileUri } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';

@Component
export default struct KnockShareScreen {
  @State knockShareScreenX: number | undefined = undefined;
  @State knockShareScreenY: number | undefined = undefined;
  @State dataReceiveScreenX: number | undefined = undefined;
  @State dataReceiveScreenY: number | undefined = undefined;

  aboutToAppear(): void {
    this.knockShareListening();
  }

  private knockShareListening() {
    harmonyShare.on('knockShare', this.knockShareCallback);

    let capabilityRegistry: harmonyShare.RecvCapabilityRegistry = {
      windowId: 999,
      capabilities: [{
        utd: utd.UniformDataType.IMAGE,
        maxSupportedCount: 1
      }]
    }
    harmonyShare.on('dataReceive', capabilityRegistry, this.dataReceiveCallback);
  }

  private knockShareCallback = (sharableTarget: harmonyShare.SharableTarget) => {
    let uiContext: UIContext = this.getUIContext();
    let contextFaker: Context = uiContext.getHostContext() as Context;
    let filePath = contextFaker.filesDir + '/exampleKnock1.jpg';
    let shareData: systemShare.SharedData = new systemShare.SharedData({
      utd: utd.UniformDataType.JPEG,
      uri: fileUri.getUriFromPath(filePath),
      thumbnailUri: fileUri.getUriFromPath(filePath)
    });
    let sharableTargetInfo = sharableTarget.getInfo();
    this.knockShareScreenX = sharableTargetInfo.coordinate?.screenX;
    this.knockShareScreenY = sharableTargetInfo.coordinate?.screenY;
    sharableTarget.share(shareData);
  }

  private dataReceiveCallback = (receivableTarget: harmonyShare.ReceivableTarget) => {
    let uiContext: UIContext = this.getUIContext();
    let context = uiContext.getHostContext() as common.UIAbilityContext;
    let sandboxUri = fileUri.getUriFromPath(context.filesDir);
    let receivableTargetInfo = receivableTarget.getInfo();
    this.dataReceiveScreenX = receivableTargetInfo.coordinate?.screenX;
    this.dataReceiveScreenY = receivableTargetInfo.coordinate?.screenY;
    receivableTarget.receive(sandboxUri, {
      onDataReceived: (sharedData: systemShare.SharedData) => {
        // do something.
      },
      onResult: (resultCode: harmonyShare.ShareResultCode) => {
        if (resultCode === harmonyShare.ShareResultCode.SHARE_SUCCESS) {
          // do something.
        }
      }
    });
  }

  build() { }
}

手机与 PC/2in1、手机与 Tablet 间相互分享

Phone 与 PC/2in1 设备间相互分享,以及从 6.1.0(23) 版本开始的 Phone 与 Tablet 设备间相互分享,可参考“手机间内容分享”部分的开发方式。

总结

鸿蒙系统的碰一碰功能通过 Share Kit 提供了便捷的超近场分享能力,覆盖手机与手机、手机与 PC/2in1、手机与 Tablet 等多种设备组合。开发者在适配时需要关注:

  • 界面设计:根据分享内容选择合适的卡片模板,并设置符合要求的预览图。
  • 事件注册:使用 harmonyShare.on('knockShare') 注册发送事件,使用 harmonyShare.on('dataReceive') 注册接收事件。
  • 参数配置:正确设置 SendCapabilityRegistryRecvCapabilityRegistry 中的 windowIdcapabilities 等参数。
  • 异常处理:在无法分享或接收时,调用 clarifyNonShare()reject() 方法及时终止。
  • 高级能力:支持预览图延迟更新、单向分享、沙箱接收、获取轻碰坐标等,满足不同业务场景需求。

通过合理利用以上能力,开发者可以为用户提供流畅、直观的碰一碰分享体验。

Logo

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

更多推荐