跳到主要内容鸿蒙 Share Kit 碰一碰分享功能开发指南 | 极客日志TypeScript大前端
鸿蒙 Share Kit 碰一碰分享功能开发指南
本文介绍 HarmonyOS Share Kit 的碰一碰分享能力,涵盖手机间及手机与 PC/2in1 协同场景。内容包含环境要求、核心业务流程、事件注册、数据构造、预览图优化、App Linking 与 Deep Linking 选择、安全策略及异常处理。通过代码示例详解如何注册监听、发送共享数据、沙箱接收及组队邀请开发,帮助开发者实现跨设备一碰即传体验。
HarmonyOS 的 Share Kit 推出的'碰一碰分享'能力,通过'设备轻触'这一直观交互,将跨端分享简化为'一碰即传',支持图片、文件、Wi-Fi、组队邀请等多场景。本文将结合官方开发文档,从手机间分享、手机与 PC/2in1 协同两大场景,详解开发流程、核心代码与避坑要点。
一、碰一碰分享核心基础:环境与核心概念
在开始开发前,需先明确功能依赖的环境要求与核心逻辑,避免因版本不兼容导致功能失效。
1.1 环境要求(必看!)
不同设备间的碰一碰分享,对系统版本和开发工具的要求不同,具体如下:
| 手机与手机 | 双端均为 HarmonyOS NEXT Release 及以上(推荐 5.0+) | DevEco Studio NEXT Beta1+ |
| 手机与 PC/2in1 | 手机:同上方;PC/2in1:HarmonyOS 6.0.0 Beta1+ | DevEco Studio 6.0.0 Beta1+ |
关键检查:通过 canIUse 判断设备是否支持碰一碰能力,避免在不支持的设备上触发无效逻辑:
if(canIUse('SystemCapability.Collaboration.HarmonyShare')){
console.log("设备支持碰一碰分享,可初始化相关逻辑");
} else {
console.log("设备不支持碰一碰分享,需隐藏相关引导");
}
1.2 核心业务流程
无论哪种场景,碰一碰分享的核心流程都遵循'注册→触发→传输→解除'四步,以手机与手机为例:
- 注册事件:宿主应用进入可分享界面(如选中图片、打开 Wi-Fi 详情)时,注册碰一碰分享监听;
- 触发交互:双端设备亮屏、解锁且开启华为分享(关闭则弹窗提示开启),顶端轻碰;
- 数据传输:源端构造分享数据(如图片 URI、链接)并发送,目标端接收并拉起对应应用;
- 解除监听:离开可分享界面(如关闭图片、退出页面)时,解除碰一碰监听,避免内存泄漏。
二、手机与手机碰一碰开发:从预览到异常处理
手机间碰一碰是最基础的场景,需重点关注预览体验、数据传输方式、安全策略与异常兜底,以下分模块详解。
2.1 第一步:引导用户触发——注册碰一碰事件
用户可能不清楚'何时可碰',需在可分享界面添加引导(文本 + 动图),提升交互感知。
2.1.1 引导资源集成
- 下载资源包:碰一碰引导资源(完整下载
knock_share_guide 目录);
- 放置路径:将资源放入应用
entry/src/main/resources/rawfile 目录;
- 界面引导:在可分享界面(如图片预览页)显示文本提示 + 动图,示例文案:
- '可碰一碰分享至 HarmonyOS 5 及以上版本手机'
- '对方需在控制中心开启'华为分享''
2.1.2 注册监听事件
在页面 aboutToAppear 生命周期中注册碰一碰事件,aboutToDisappear 中解除,确保资源释放:
import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { fileUri } from '@kit.CoreFileKit';
import { UIContext, Context } from '@kit.ArkUI';
@Component
export default struct ImageSharePage {
aboutToAppear(): void {
this.registerKnockShare();
}
aboutToDisappear(): void {
this.unregisterKnockShare();
}
private registerKnockShare() {
const capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
windowId: 1001,
};
harmonyShare.on('knockShare', capabilityRegistry, (sharableTarget: harmonyShare.SharableTarget) => {
this.buildShareData(sharableTarget);
});
}
private unregisterKnockShare() {
const capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
windowId: 1001,
};
harmonyShare.off('knockShare', capabilityRegistry);
}
private buildShareData(sharableTarget: harmonyShare.SharableTarget) {
const uiContext: UIContext = this.getUIContext();
const context: Context = uiContext.getHostContext() as Context;
const imagePath = context.filesDir + '/shared_image.jpg';
const thumbnailUri = fileUri.getUriFromPath(imagePath);
const shareData: systemShare.SharedData = new systemShare.SharedData({
utd: utd.UniformDataType.IMAGE,
content: thumbnailUri,
title: '旅行照片',
description: '2025 年夏日旅行',
thumbnailUri: thumbnailUri,
});
sharableTarget.share(shareData);
}
build() {
}
}
2.2 第二步:优化视觉体验——设置分享预览
分享卡片的预览效果直接影响用户接受度,Share Kit 提供 3 种卡片模板,需根据分享内容类型选择:
| 模板类型 | 适用场景 | 配置要求 | 布局约束 |
|---|
| 纯图片布局 | 文件、图片(无需文字说明) | 仅传递 thumbnailUri | 预览图宽高比≥1:4,超出部分裁剪 |
| 沉浸式大卡布局 | 链接(需展示文字) | 同时传递 title+description+thumbnailUri,且预览图宽高比<1:1 | 标题最多 2 行(超出省略),描述 1 行,显应用图标 |
| 白卡上下布局 | 链接(需展示文字) | 同时传递 title+description+thumbnailUri,且预览图宽高比>1:1 | 同上,预览图仅占卡片上方,不铺满 |
2.2.1 预览图最佳实践
预览图分辨率影响加载速度与清晰度,推荐按以下标准设置(文档 2):
| 预览图来源 | 推荐比例 | 推荐分辨率(px) |
|---|
| 应用海报 | 3:4 | 最小 600_800,最大 3000_4000 |
| 用户上传图片 | 无限制 | 最大 3000*4000(避免过大) |
2.2.2 预览图延迟更新(解决云端图片问题)
若预览图存储在云端(如 OSS),碰一碰触发时可能未下载完成,导致卡片空白。可先发送核心数据,待图片下载后更新预览:
private buildShareData(sharableTarget: harmonyShare.SharableTarget) {
const shareData: systemShare.SharedData = new systemShare.SharedData({
utd: utd.UniformDataType.HYPERLINK,
content: 'https://example.com/travel',
title: '旅行攻略',
description: '超全景点指南',
});
sharableTarget.share(shareData);
setTimeout(async () => {
const uiContext: UIContext = this.getUIContext();
const context: Context = uiContext.getHostContext() as Context;
const downloadedImagePath = context.filesDir + '/downloaded_poster.jpg';
const newThumbnailUri = fileUri.getUriFromPath(downloadedImagePath);
sharableTarget.updateShareData({
thumbnailUri: newThumbnailUri,
});
}, 3000);
}
2.3 第三步:选择数据传输方式——App Linking vs Deep Linking
若分享内容为'链接'(如商品页、文章页),需通过以下两种方式实现应用跳转,核心区别在于'未安装应用时的处理逻辑'。
2.3.1 App Linking(推荐)
- 已安装:直接拉起应用并打开链接;
- 未安装:跳转应用市场(需集成 App Linking Kit);
- 支持延迟链接:应用下载后仍能获取之前的分享链接。
private buildShareData(sharableTarget: harmonyShare.SharableTarget) {
const shareData: systemShare.SharedData = new systemShare.SharedData({
utd: utd.UniformDataType.HYPERLINK,
content: 'https://sharekitdemo.drcn.agconnect.link/ZB3p',
title: '华为商城新品',
description: 'nova 14 系列限时优惠',
thumbnailUri: 'file:///data/storage/.../poster.jpg',
});
sharableTarget.share(shareData);
}
2.3.2 Deep Linking(简单但有局限)
局限:仅在目标端已安装应用时生效,未安装则弹窗提示'暂无可用打开方式'。
content: 'myapp://product/detail?id=123',
2.4 第四步:保障安全与体验——安全策略与异常处理
2.4.1 安全策略:明确设备/账号身份
为避免用户接收陌生设备的分享,Share Kit 会显示发送端/接收端的身份信息(需 HarmonyOS NEXT 5.0.0.123 SP16 及以上版本):
| 角色 | 对端已登录华为账号 | 对端未登录华为账号 |
|---|
| 发送端 | 显示接收端账号昵称 + 头像 | 显示接收端设备名(如'Mate 70') |
| 接收端 | 显示发送端账号昵称 + 头像 | 显示发送端设备名 |
注意:SP16 之前的版本不显示任何身份信息,开发时需考虑版本兼容。
2.4.2 异常场景处理
harmonyShare.on('knockShare', (sharableTarget: harmonyShare.SharableTarget) => {
sharableTarget.clarifyNonShare({ message: '当前界面不支持碰一碰,请在图片预览或文件详情页尝试' });
});
harmonyShare.on('knockShare', (sharableTarget: harmonyShare.SharableTarget) => {
const downloadFailed = true;
if (downloadFailed) {
sharableTarget.reject(harmonyShare.SharableErrorCode.DOWNLOAD_ERROR);
}
});
三、手机与 PC/2in1 碰一碰开发:跨端协同新体验
手机与 PC/2in1 的碰一碰进一步拓展场景(如手机传图到 PC 编辑、PC 传文档到手机),需关注双向分享限制与沙箱接收特性。
3.1 核心约束与环境
- 账号要求:手机与 PC/2in1 必须登录相同华为账号;
- 设备形态:仅支持手机直板态/折叠手机直板态,不支持折叠态;
- 角度约束(触发成功率关键):
- 手机与 PC 屏幕俯视夹角≤5°(尽量平行);
- 侧视夹角>35°(避免过度倾斜);
- 正视夹角≤25°(正对屏幕);
- 保护壳:仅支持官方轻薄保护壳,过厚壳会影响感应。
3.2 双向分享限制(避坑要点)
从 HarmonyOS 6.0.0 Beta5 开始,手机与 PC/2in1 不支持'双向同时分享',遵循以下优先级:
- 若手机前台有可分享内容(如打开图片),则手机为发送端,PC 为接收端;
- 若手机前台无内容,但 PC 前台有可分享内容(如打开文档),则PC 为发送端,手机为接收端;
- 若两者均无内容,触发'无内容分享'提示。
注意:Beta5 之前的版本支持双向分享(双方同时发送接收),开发时需根据版本适配逻辑。
3.3 分享内容直达应用:沙箱接收
PC/2in1 支持'沙箱接收',即手机碰 PC 后,文件直接传入 PC 应用的沙箱目录,无需用户选择保存路径,实现'直达编辑'(如手机传图到 PC 版 PS,直接打开编辑)。
3.3.1 沙箱接收开发步骤
import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { common } from '@kit.AbilityKit';
@Component
export default struct PCImageEditorPage {
aboutToAppear(): void {
this.registerSandboxReceive();
}
aboutToDisappear(): void {
this.unregisterSandboxReceive();
}
private registerSandboxReceive() {
const capabilityRegistry: harmonyShare.RecvCapabilityRegistry = {
windowId: 2001,
capabilities: [
{
utd: utd.UniformDataType.IMAGE,
maxSupportedCount: 5,
},
],
};
harmonyShare.on('dataReceive', capabilityRegistry, (receivableTarget: harmonyShare.ReceivableTarget) => {
const uiContext = this.getUIContext();
const context = uiContext.getHostContext() as common.UIAbilityContext;
const savePath = context.filesDir + '/received_images/';
receivableTarget.receive(savePath, {
onDataReceived: (sharedData: systemShare.SharedData) => {
const records = sharedData.getRecords();
records.forEach((record) => {
console.log(`接收文件:${record.uri}`);
this.openImageEditor(record.uri);
});
},
onResult: (resultCode: harmonyShare.ShareResultCode) => {
if (resultCode === harmonyShare.ShareResultCode.SHARE_SUCCESS) {
console.log("所有文件接收完成");
} else {
console.log(`接收失败,错误码:${resultCode}`);
}
},
});
});
}
private unregisterSandboxReceive() {
const capabilityRegistry: harmonyShare.RecvCapabilityRegistry = {
windowId: 2001,
capabilities: [
{
utd: utd.UniformDataType.IMAGE,
maxSupportedCount: 5,
},
],
};
harmonyShare.off('dataReceive', capabilityRegistry);
}
private openImageEditor(imageUri: string) {
}
build() {
}
}
3.3.2 拒绝沙箱接收
若应用当前无法接收(如编辑中),可调用 reject 拒绝:
harmonyShare.on('dataReceive', (receivableTarget: harmonyShare.ReceivableTarget) => {
if (this.isEditing) {
receivableTarget.reject(harmonyShare.ReceivableErrorCode.NO_RECEIVABLE_ERROR);
}
});
四、特殊场景:组队邀请开发
在游戏、运动类应用中,可通过碰一碰发起'组队邀请',需避免'双方同时邀请'导致的冲突,此时需使用单向分享能力。
4.1 核心代码:注册单向分享
aboutToAppear(): void {
const capabilityRegistry: harmonyShare.SendCapabilityRegistry = {
windowId: 3001,
sendOnly: true,
};
harmonyShare.on('knockShare', capabilityRegistry, (sharableTarget) => {
const teamLink = `mygame://team/join?id=12345&inviter=user1`;
const shareData = new systemShare.SharedData({
utd: utd.UniformDataType.HYPERLINK,
content: teamLink,
title: '邀请加入游戏战队',
description: '点击立即组队开黑',
thumbnailUri: 'file:///.../team_poster.jpg',
});
sharableTarget.share(shareData);
});
}
4.2 冲突处理
- 若双方均设置
sendOnly: true:系统终止分享,提示'请任意一方退出当前应用后再试';
- 若仅一方设置:分享成功,目标端拉起应用并通过
onNewWant 获取组队链接。
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
export default class GameAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (want.uri) {
console.log(`收到组队邀请:${want.uri}`);
this.joinTeam(want.uri);
}
}
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
if (want.uri) {
this.joinTeam(want.uri);
}
}
private joinTeam(teamUri: string) {
}
}
五、开发最佳实践总结
- 环境检查优先:通过
canIUse 判断设备能力,避免无效逻辑;
- 资源及时释放:在
aboutToDisappear 中解除碰一碰监听,防止内存泄漏;
- 预览图适配:按推荐分辨率设置预览图,云端图片用延迟更新兜底;
- 异常全面覆盖:处理'无内容''下载失败'等场景,避免用户无反馈;
- 跨端版本适配:手机与 PC 的系统版本要求不同,双向分享限制需区分版本;
- 用户引导清晰:在可分享界面添加文本 + 动图引导,降低使用门槛。
希望开发者可以通过以上开发指南,快速实现 HarmonyOS 碰一碰分享功能,为用户提供'一碰即传'的跨端体验。随着鸿蒙生态的扩展,未来碰一碰还将支持更多设备(如平板、智慧屏),进一步丰富全场景交互。
微信扫一扫,关注极客日志
微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
- JSON美化和格式化
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online