目录
一、背景与痛点
传文件最烦的是"先开 App、再选设备、再等配对"。HarmonyOS 的精准碰一碰(NearLink / 碰一碰分享)把这一步压缩成"两台设备靠近一碰,文件就过去了",配合拖拽投送还能把图直接拖进对方窗口。但真做接入,我遇到:设备不支持、距离太远拉不起、权限没配导致静默失败、大文件传输中断。
碰一碰底层是近场发现 + 近场传输,开发侧主要和分享意图(Want)+ 近场能力打交道。本文讲清接入链路与避坑。
二、能力与规格
| 维度 | 说明 |
|---|---|
| 能力 | 近场发现、近场分享、拖拽投送 |
| 依赖 | 设备需支持 NearLink / 碰一碰硬件与系统版本 |
| 入口 | 系统分享面板(Want sendData)+ 近场投送通道 |
| 约束 | 距离近(厘米级)、需双方亮屏解锁、权限与可见性 |
| 典型场景 | 图片/视频碰传、会议纪要投送、跨设备接力 |
三、核心代码(发起近场分享)
typescript
import { wantConstant } from '@kit.AbilityKit';
import { fileUri } from '@kit.CoreFileKit';
import { nearbyShare } from '@kit.NearLinkKit'; // 近场能力查询/传输
// 1. 把沙箱文件转成可分享 URI
function toShareUri(sandboxPath: string): string {
return fileUri.getUriFromPath(sandboxPath); // 如 file://...
}
// 2. 能力探测:先确认设备支持碰一碰,避免按钮点了没反应
function isNearbySupported(): boolean {
return nearbyShare.isSupported(); // 低端机/旧版本返回 false
}
// 3. 构造分享 Want,交给系统分享面板(碰一碰会在面板里出现)
function shareNearby(ctx: Context, filePath: string): void {
if (!isNearbySupported()) {
// 降级:走普通二维码/蓝牙分享
fallbackShare(ctx, filePath);
return;
}
const want: Want = {
action: wantConstant.Action.sendData,
type: 'image/jpeg', // MIME,决定接收方可识别
uri: toShareUri(filePath),
parameters: { 'ohos.extra.param.key_share_target': 'nearby' },
};
// 拉起系统分享,用户选"碰一碰/近场"即可近场发送
(ctx as common.UIAbilityContext).startAbility(want)
.catch(err => console.error('share failed', err));
}
// 4. 降级方案:二维码/蓝牙分享
function fallbackShare(ctx: Context, filePath: string): void {
// 生成二维码或走蓝牙通道,保证功能可用
console.info('device not support nearby, fallback to qrcode/bluetooth');
}
// 5. 大文件进度回调:监听传输进度,UI 上提示"保持设备靠近"
function watchProgress(taskId: string): void {
nearbyShare.on('progress', (info: ProgressInfo) => {
const percent = Math.round(info.transferred / info.total * 100);
console.info(`transfer progress: ${percent}%`);
// 更新 UI 进度条,并提示用户保持设备靠近
});
nearbyShare.on('interrupt', () => {
console.warn('transfer interrupted, retry...');
// 触发续传/重试逻辑
});
}
四、实战要点
要点 1:先确认设备能力,别假设都支持。
碰一碰依赖硬件与系统版本,低端机/旧版本可能没有。发起前用能力查询判断,不支持就降级成普通二维码/蓝牙分享,别让按钮点了没反应。
要点 2:URI 必须用 getUriFromPath 转换。
直接塞沙箱绝对路径,接收方拿不到(跨应用沙箱隔离)。一定要转成 file:// 形式的分享 URI。
要点 3:MIME type 写准,否则接收端不认。
type 决定对方用什么打开。图片用 image/jpeg、视频 video/mp4,乱写会导致接收方无应用可处理,传输白做。
要点 4:大文件做好中断与进度。
近场传输受距离、干扰影响可能中断。大文件务必带进度回调与续传/重试,并在 UI 上明示"保持设备靠近",别让用户以为卡死了。
五、进阶:接收端与权限配置
碰一碰是双向的,发送端只是链路的一半。接收端要能"接住"文件,还需要做好三件事:
1. 声明接收能力(module.json5)
接收方要在 module.json5 里声明 sendData 的 want 过滤,否则系统分享面板不会把文件投给它:
json5
{
"abilities": [
{
"name": "ReceiveAbility",
"skills": [
{
"actions": ["ohos.want.action.sendData"],
"uris": [
{ "scheme": "file", "type": "image/*" },
{ "scheme": "file", "type": "video/*" }
]
}
]
}
]
}
2. 在 onNewWant 里接收文件
typescript
import { fileUri } from '@kit.CoreFileKit';
export default class ReceiveAbility extends UIAbility {
onNewWant(want: Want): void {
const uri = want.uri; // file:// 形式的分享 URI
if (!uri) return;
// 转回沙箱路径并落盘
const sandboxPath = fileUri.getPathFromUri(uri);
console.info(`received file at: ${sandboxPath}`);
// 通知 UI 展示接收结果
}
}
3. 权限与可见性
- 双方需亮屏解锁,且开启"碰一碰/近场分享"开关;
- 首次使用会弹权限确认,务必在 UI 上引导用户授权;
- 距离过远(超过厘米级)会拉不起,UI 上要提示"请将设备靠近"。
六、小结与边界
碰一碰适合小文件快速近场投送 (图片、短视频、纪要),是"无感分享"的典范。它强依赖硬件与近距离,不适合大体积离线同步。落地记住:能力先探测、URI 要转换、MIME 写准、大文件带进度、接收端要声明。发送与接收两端都配好,链路才算完整。
本文为原创首发实战笔记,基于 HarmonyOS 近场分享/碰一碰能力,代码示例为调用范式示意,实际接口以华为官方文档为准。
七、总结
本文围绕 HarmonyOS 精准碰一碰(NearLink)近场分享能力,梳理了从背景痛点、能力规格、核心代码到实战要点的完整接入链路。核心收获可归纳为四点:
- 能力先探测:发起前确认设备是否支持 NearLink / 碰一碰,不支持时降级为二维码或蓝牙分享,避免按钮无响应。
- URI 要转换 :沙箱绝对路径无法跨应用传递,必须用
getUriFromPath转成file://分享 URI。 - MIME 写准 :
type决定接收端如何打开文件,图片用image/jpeg、视频用video/mp4,写错会导致接收方无应用可处理。 - 大文件带进度:近场传输易受距离与干扰影响,务必提供进度回调、续传/重试,并在 UI 上提示"保持设备靠近"。
碰一碰适合小文件快速近场投送(图片、短视频、纪要),是无感分享的典范;但它强依赖硬件与近距离,不适合大体积离线同步。落地时按上述四点逐一核对,即可显著降低接入失败率。