HarmonyOS 6.1 华为分享实战:让《左右相册》的每一张照片都能触动人心

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 的华为分享能力,把这两件事无缝连接在一起——你在整理回忆的同时,也在传递回忆。


参考资料

编辑于 2026-05-21 · 著作权归作者所有