HarmonyOS 7 Share Kit + ShareExtensionAbility 实战:系统分享面板、数据接收与跨应用内容流转

把内容分享出去容易,把别人分享过来的内容正确接住才是真麻烦。

文章封面

做笔记应用的时候,最开始只做了"分享出去":写完笔记点分享,把文本和图片传给其他应用。这个功能很简单,调用 Share Kit 的 API 就完事了。

后来用户提需求:能不能在相册里选一张图,直接分享到我们的笔记应用里?这时候才发现,"接收分享"比"分享出去"麻烦多了——要配置接收类型、要解析跨应用传过来的数据、要处理各种异常情况、还要管理分享页面的生命周期。

这篇就沿着"一张图片从相册跑到笔记应用"这条链路,把整个分享接收流程拆清楚。

一、一张图片的跨应用旅程

先把整个链路理一遍:

相册应用
  ↓ 调用系统分享
系统分享面板
  ↓ 用户选择笔记应用
笔记应用 ShareExtensionAbility
  ↓ 接收 SharedData
解析数据 → 保存图片 → 创建笔记

整个过程可以想成"寄快递":

  • 发送方把内容打包成 SharedData;
  • 系统分享面板是快递公司,负责路由;
  • 接收方的 ShareExtensionAbility 是收件人,负责拆包、检查、处理。

二、ShareExtensionAbility 是干什么的

ShareExtensionAbility 基于 UIExtensionAbility,它的作用就是让你的应用出现在系统分享面板里,并且能处理其他应用传过来的分享内容。

角色职责
发送方应用把内容打包成 SharedData,调用系统分享
系统分享面板展示可接收的应用列表,路由分享内容
ShareExtensionAbility(接收方)接收 SharedData,解析数据,处理业务

很多人只实现了"分享出去",没实现"接收分享"。结果就是你的应用在分享列表里根本看不到,因为你根本没注册 ShareExtensionAbility。

三、UTD 类型为什么这么重要

分享的数据不是随便传的,要有类型标识。这个类型就是 UTD(Uniform Type Description)。

UTD 类型对应内容
text/plain纯文本
image/jpegJPEG 图片
image/pngPNG 图片
file/*通用文件

你要接收什么类型的数据,就要在 module.json5 里配置对应的 UTD 类型。配置错了,系统分享面板里就不会出现你的应用,或者出现了但收不到对应类型的数据。

这段代码解决什么问题: 配置应用可接收的分享类型。
文件: entry/src/main/module.json5
用途: 注册 ShareExtensionAbility 接收类型
接入位置: ExtensionAbility 配置

"extensionAbilities": [
  {
    "name": "ShareReceiverAbility",
    "type": "shareReceiver",
    "metadata": {
      "utd": ["text/plain", "image/jpeg", "image/png"],
      "maxFileSupported": 20
    }
  }
]

这里配置了可以接收文本、JPEG、PNG 三种类型,最多支持 20 个文件。maxFileSupported 很重要——超过这个数量,系统就不会把你的应用显示在分享列表里了。

四、收到数据之后怎么解析

用户选了你的应用之后,ShareExtensionAbility 的 onSessionCreate 会被调用,里面带着传过来的 SharedData。

这段代码解决什么问题: 解析接收到的分享数据。
文件: ShareReceiverAbility.ets
用途: 接收并处理分享内容
接入位置: onSessionCreate 生命周期

import ShareExtensionAbility from '@ohos.app.ability.ShareExtensionAbility';
import Want from '@ohos.app.ability.Want';

export default class ShareReceiver extends ShareExtensionAbility {
  onSessionCreate(want: Want, session) {
    const sharedData = want?.parameters?.sharedData;
    const records = sharedData?.records || [];
    
    for (const record of records) {
      if (record.utd === 'image/jpeg' || record.utd === 'image/png') {
        this.saveImage(record.uri);
      } else if (record.utd === 'text/plain') {
        this.saveText(record.content);
      }
    }
    this.finishShare();
  }
}

这里要注意:不同类型的 record 结构不一样。图片类型的 record 里是文件 URI,文本类型的 record 里是 content 字段。不能所有 record 都按同一种方式解析。

五、URI 为什么不能直接当路径用

这是最容易踩的坑。接收过来的图片 URI,不是应用沙箱里的文件路径,是系统媒体库的资源标识。

错误做法正确做法
把 URI 直接当文件路径打开通过系统 Kit 的接口读取资源
拼接字符串猜真实路径用文件管理接口按 URI 读取
长期缓存 URI 直接用读取后复制到应用沙箱再使用

跨应用传过来的 URI 是有访问权限的,不是永久有效的。处理完之后最好把文件复制到自己的应用沙箱里,再做后续处理。

时序图

六、Session 为什么必须正确结束

处理完分享内容之后,必须调用 finishShare 或者 session.terminate() 结束这次分享会话。

如果不结束会怎么样?系统分享面板一直挂着,用户操作完了页面不消失,体验很差。更严重的是,Session 不结束,资源一直不释放,占着内存。

还有异常情况:如果处理数据出错了,不能只写个日志就不管了。要给用户一个提示,然后正常结束 Session。不能让系统分享面板卡在那里。

七、几个容易踩的坑

第一个坑:只做"分享出去",没做"接收分享"。结果应用在分享列表里都不出现。

第二个坑:UTD 类型配置错误。配置的类型和实际要接收的类型对不上,要么收不到数据,要么系统不显示。

第三个坑:图片数量超过 maxFileSupported。一次分享了 30 张图,但配置的最多支持 20 张,那你的应用直接从分享列表里消失了。

第四个坑:把 URI 当普通文件路径。跨应用传过来的 URI 不是沙箱路径,直接 open 会失败。

第五个坑:所有数据类型都按同一种方式解析。文本和图片的 record 结构不一样,混着解析就会出错。

运行效果图

这次做分享接收功能最大的体会是:分享出去只是把数据打包扔出去,接收分享才是真正的工程活。要配置类型、要解析数据、要处理 URI、要管理 Session、要处理异常。看起来就是"点一下分享按钮"的事,背后有一整套跨应用数据流转的机制在跑。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值