
HarmonyOS 6.1 华为分享实战:让《左右相册》的每一张照片都能触动人心
前言
整理相册,本是一件私密的事。
但当你在《左右相册》里随机翻到一张三年前的合影——那个下午的阳光、朋友的笑脸——你的第一反应不是删除,而是想把它发给那个人。
这就是分享的意义:整理的终点,往往是连接的起点。
《左右相册》是一款基于 HarmonyOS 开发的照片整理应用,核心交互是左右滑动决定照片去留。在集成华为分享能力之前,用户只能独自面对那些照片。接入 @kit.ShareKit 之后,每一张勾起回忆的照片,都可以在两秒内送达对方。

为什么整理类应用需要分享?
很多人认为"整理工具"和"社交分享"是两个独立的场景。但实际使用中,它们高度重叠:
- 翻到旧照片 → 想发给当事人
- 发现一段珍贵视频 → 想立刻分享给家人
- 两台手机靠近 → 碰一碰,照片直达对方图库
分享不是附加功能,而是整理行为的自然延伸。 如果用户必须先退出应用、打开相册、再找到照片才能分享,这个摩擦足以让那个"想分享"的冲动消失。
华为分享能力概览
@kit.ShareKit 提供了两种分享方式,恰好覆盖了《左右相册》的两个核心场景:
| 方式 | API | 适用场景 |
|---|---|---|
| 系统面板分享 | systemShare.ShareController | 点击分享按钮,选择微信/短信/蓝牙等 |
| 碰一碰分享 | harmonyShare.on('knockShare') | 两台华为设备靠近,照片直达对方图库 |
工具类封装:ShareUtil
为了让分享逻辑与 UI 解耦,项目将所有分享能力封装进一个静态工具类 ShareUtil.ets:
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { common } from '@kit.AbilityKit';
import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { fileUri } from '@kit.CoreFileKit';
import { BusinessError } from '@kit.BasicServicesKit';
export class ShareUtil {
// ── 系统面板分享图片 ──────────────────────────────────────────
static shareImage(context: common.UIAbilityContext, imagePath: string, title?: string) {
const shareData = new systemShare.SharedData({
utd: utd.UniformDataType.JPEG,
uri: fileUri.getUriFromPath(imagePath),
title: title || '分享图片',
});
const controller = new systemShare.ShareController(shareData);
controller.show(context, {
previewMode: systemShare.SharePreviewMode.DETAIL,
selectionMode: systemShare.SelectionMode.SINGLE,
}).catch((error: BusinessError) => {
console.error(`分享失败: ${error.code}, ${error.message}`);
});
}
// ── 系统面板分享视频 ──────────────────────────────────────────
static shareVideo(context: common.UIAbilityContext, videoPath: string, title?: string) {
const shareData = new systemShare.SharedData({
utd: utd.UniformDataType.VIDEO,
uri: fileUri.getUriFromPath(videoPath),
title: title || '分享视频',
});
const controller = new systemShare.ShareController(shareData);
controller.show(context, {
previewMode: systemShare.SharePreviewMode.DETAIL,
selectionMode: systemShare.SelectionMode.SINGLE,
}).catch((error: BusinessError) => {
console.error(`分享失败: ${error.code}, ${error.message}`);
});
}
// ── 碰一碰分享:开启监听 ──────────────────────────────────────
static startKnockShare(filePath: string, utdType: string = utd.UniformDataType.JPEG) {
const callback = (sharableTarget: harmonyShare.SharableTarget) => {
const shareData = new systemShare.SharedData({
utd: utdType,
uri: fileUri.getUriFromPath(filePath),
thumbnailUri: fileUri.getUriFromPath(filePath),
});
sharableTarget.share(shareData);
};
harmonyShare.on('knockShare', callback);
return callback; // 返回引用,用于后续注销
}
// ── 碰一碰分享:停止监听 ──────────────────────────────────────
static stopKnockShare(callback: (sharableTarget: harmonyShare.SharableTarget) => void) {
harmonyShare.off('knockShare', callback);
}
}
设计要点:
- 全部静态方法,无需实例化,调用方式简洁
startKnockShare返回 callback 引用,调用方持有并在适当时机注销,避免内存泄漏- 图片和视频分别指定
utd类型,确保接收端正确识别文件格式
在照片浏览页集成
照片浏览页(PhotoBrowserPage)是分享的主战场。用户在这里左右滑动浏览照片,随时可能想分享当前这张。

系统面板分享
顶部栏放置分享按钮,点击即弹出系统分享面板:
Image($r('app.media.ic_pic_share'))
.fillColor(Color.White)
.width(20).height(20)
.onClick(() => {
const photo = this.photos[this.currentIndex];
const ctx = getContext(this) as common.UIAbilityContext;
ShareUtil.shareImage(ctx, photo.uri, photo.displayName);
})

碰一碰分享:随照片切换自动更新
碰一碰的关键在于:监听的目标要始终是当前正在看的那张照片。用户滑到哪张,碰一碰就分享哪张。
// 页面就绪时,对第一张照片开启监听
private knockCallback?: (target: harmonyShare.SharableTarget) => void;
private startKnockShare() {
this.knockCallback = ShareUtil.startKnockShare(this.currentUri);
}
// 照片切换时,注销旧监听,注册新监听
onIndexChange: (visibleIndex: number) => {
const photo = this.visiblePhotos[visibleIndex];
this.currentUri = photo.uri;
if (this.knockCallback) {
ShareUtil.stopKnockShare(this.knockCallback);
}
this.knockCallback = ShareUtil.startKnockShare(this.currentUri);
}
// 页面销毁时注销,防止泄漏
aboutToDisappear() {
if (this.knockCallback) {
ShareUtil.stopKnockShare(this.knockCallback);
}
}
这样实现后,用户浏览到某张照片,直接把手机靠近朋友的手机,照片就直达对方图库——零操作,零摩擦。
在视频浏览页集成
视频页(VideoListView)同样集成了系统面板分享,右侧操作栏加入分享按钮:
Image($r('app.media.ic_video_share'))
.width(40).height(40)
.onClick(() => {
const idx = Math.round(this.scrollPos);
if (idx < this.videos.length) {
const ctx = getContext(this) as common.UIAbilityContext;
ShareUtil.shareVideo(ctx, this.videos[idx].uri, this.videos[idx].displayName);
}
})


接收端体验
根据华为分享规则,发送媒体类型文件时:
- 接收端(手机):照片/视频直接进入图库"华为分享"相册,并以大图预览方式展示
- 无需安装同款应用,系统原生接收,体验无缝
这意味着用户不需要对方也安装《左右相册》,只要是华为设备,碰一碰就能完成传递。
技术要点总结
1. 权限配置
在 module.json5 中添加媒体库读写权限:
"requestPermissions": [
{
"name": "ohos.permission.READ_IMAGEVIDEO",
"reason": "$string:attention",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.WRITE_IMAGEVIDEO",
"reason": "$string:attention",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]2. 依赖导入
import { systemShare, harmonyShare } from '@kit.ShareKit';
import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { fileUri } from '@kit.CoreFileKit';
3. 生命周期管理
| 时机 | 操作 |
|---|---|
| 页面就绪 | startKnockShare(currentUri) |
| 照片切换 | stopKnockShare() + startKnockShare(newUri) |
| 页面销毁 | stopKnockShare() |
总结
| 功能 | 实现方式 | 用户体验 |
|---|---|---|
| 点击分享图片/视频 | systemShare.ShareController | 弹出系统面板,选择任意渠道发送 |
| 碰一碰传照片 | harmonyShare.on('knockShare') | 靠近即传,直达对方图库 |
| 切换照片自动更新碰一碰目标 | stop + start 重新注册 | 始终分享当前浏览的那张 |
整理照片是一个人的事,但分享照片是两个人的事。《左右相册》通过 HarmonyOS 6.1 的华为分享能力,把这两件事无缝连接在一起——你在整理回忆的同时,也在传递回忆。