前言

你有没有被"分享到微信"这个功能折磨过?不同平台调用方式不同,回调逻辑各异,光是适配就能把人搞疯。HarmonyOS7 的 Share Kit 终于把这事儿整明白了——统一的分享面板、标准的数据格式、一套代码搞定所有分享场景。今天就来聊聊怎么用。

A hand-drawn doodle illustration on pure white pap

说实话,我之前对"系统级分享"这事儿没太大期待。毕竟 Android 的 Intent 分享机制用了很多年,该有的坑一个没少。但 Share Kit 真的不一样,它不光提供了统一的分享入口,还把发送端和接收端的数据协议全给你标准化了。用 UTD(统一数据类型)替代了以前乱七八糟的 MIME 类型判断,这事儿做得太对了。

分享方式对比

先看个表格,搞清楚 HarmonyOS7 里几种分享方式的区别:

分享方式 触发方式 典型场景 是否跨设备
系统分享面板 用户点击"分享"按钮 分享文本、图片到社交App
碰一碰分享 两台设备物理轻触 近场名片、文件互传
隔空传送 手势感应(无需接触) 跨设备文件/链接推送
应用内跳转 Want 隐式调用 打开指定App的特定页面

日常开发中最常用的就是系统分享面板,这也是今天的主角。

Share Kit 接入

A hand-drawn doodle illustration on pure white pap

接入 Share Kit 只需要两步:导入模块 + 构造数据。代码很简单,但有几个细节容易踩坑。

import { systemShare } from '@kit.ShareKit'
import { uniformTypeDescriptor as utd } from '@kit.ArkData'
import { common } from '@kit.AbilityKit'

划重点@kit.ShareKit 是分享能力的主模块,uniformTypeDescriptor 是统一数据类型定义。这两个必须一起用,UTD 是 Share Kit 的核心——它用标准类型标识替代了以前那种 text/plainimage/png 的字符串判断方式。

构造分享数据
let sharedData: systemShare.SharedData = new systemShare.SharedData({
  utd: utd.UniformDataType.PLAIN_TEXT,
  content: '分享一段文字内容'
})

这段代码做了两件事:

  1. 指定数据类型为 PLAIN_TEXT——告诉系统你要分享的是纯文本
  2. 设置分享的具体内容

SharedData 是分享数据的容器,一个容器里可以放多条记录,每条记录用 addRecord 追加。

分享文本

最简单的场景:分享一段文字。

function shareText(text: string, context: common.UIAbilityContext) {
  let data = new systemShare.SharedData({
    utd: utd.UniformDataType.PLAIN_TEXT,
    content: text
  })
  let controller = new systemShare.ShareController(data)
  controller.on('dismiss', () => {
    console.info('分享面板已关闭')
  })
  controller.show(context, {
    previewMode: systemShare.SharePreviewMode.DETAIL,
    selectionMode: systemShare.SelectionMode.SINGLE
  })
}

A hand-drawn doodle illustration on pure white pap

逐行解释

  • ShareController 是分享控制器,传入 SharedData 即可创建
  • controller.on('dismiss', ...) 监听面板关闭事件——用户关闭分享面板后你可以做后续处理,比如更新UI状态
  • previewMode 设为 DETAIL 表示展示详细预览,另一个选项是 DEFAULT(只显示图标)
  • selectionMode 设为 SINGLE 表示单选模式(n选1),BATCH 则是批量模式

分享图片

分享图片稍微复杂一点,因为要处理文件 URI。

function shareImage(imageUri: string, context: common.UIAbilityContext) {
  let data = new systemShare.SharedData({
    utd: utd.UniformDataType.PNG,
    uri: imageUri
  })
  let controller = new systemShare.ShareController(data)
  controller.show(context, {
    previewMode: systemShare.SharePreviewMode.DETAIL,
    selectionMode: systemShare.SelectionMode.SINGLE
  })
}
关键点讲解

uri 参数是图片文件的沙箱路径,格式必须是 file://... 这种 URI 形式。你不能直接传 Resource 资源引用,得先把图片保存到沙箱目录再拿 URI。

如果你要同时分享文本和图片呢?用 addRecord

let data = new systemShare.SharedData({
  utd: utd.UniformDataType.PLAIN_TEXT,
  content: '看看这张图'
})
data.addRecord({
  utd: utd.UniformDataType.PNG,
  uri: 'file://data/storage/el2/base/files/photo.png'
})

注意addRecord 是往同一个 SharedData 里追加记录。接收方拿到的是一组数据,得遍历处理。

接收分享数据

你的 App 想出现在别人的分享面板里?得做接收端配置。这是很多教程没讲清楚的部分。

第一步:UIAbility 中处理 Want
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'
import { systemShare } from '@kit.ShareKit'

export default class ShareReceiverAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    systemShare.getSharedData(want)
      .then((data: systemShare.SharedData) => {
        let records = data.getRecords()
        records.forEach((record: systemShare.SharedRecord) => {
          console.info(`收到数据类型: ${record.utd}`)
          if (record.utd === utd.UniformDataType.PLAIN_TEXT) {
            console.info(`文本内容: ${record.content}`)
          } else if (record.utd === utd.UniformDataType.PNG) {
            console.info(`图片URI: ${record.uri}`)
          }
        })
      })
      .catch(() => {
        this.context.terminateSelf()
      })
  }
}

核心逻辑systemShare.getSharedData(want) 从系统的 Want 对象中提取分享数据。want 是系统传给你的,包含发送方打包的所有内容。拿到 SharedData 后,用 getRecords() 遍历每条记录,根据 UTD 类型分别处理。

第二步:module.json5 声明

这一步不配置就白搭,你的 App 根本不会出现在分享面板里:

"abilities": [
  {
    "name": "ShareReceiverAbility",
    "exported": true,
    "skills": [
      {
        "actions": ["ohos.want.action.sendData"],
        "uris": [
          {
            "scheme": "file",
            "utd": "general.text",
            "maxFileSupported": 1
          },
          {
            "scheme": "file",
            "utd": "general.png",
            "maxFileSupported": 1
          }
        ]
      }
    ]
  }
]

关键字段解释

  • actions 必须是 ohos.want.action.sendData,这是系统分享的固定 Action
  • uris 里穷举你支持接收的数据类型,general.text 表示文本,general.png 表示 PNG 图片
  • maxFileSupported 限制最大文件数,不填默认为 0

分享面板自定义

有时候你可能想调整分享面板的样式,比如预览模式、选择模式。Share Kit 提供了几个配置项:

配置项 可选值 说明
previewMode DETAIL / DEFAULT 详细预览 or 简略预览
selectionMode SINGLE / BATCH 单选 or 批量选择
content 字符串 自定义预览文本
utd UTD 类型 控制面板中显示的目标App

一个更完整的示例:

controller.show(context, {
  previewMode: systemShare.SharePreviewMode.DETAIL,
  selectionMode: systemShare.SelectionMode.BATCH
})

批量模式适合文件管理器这种场景——用户选中多个文件一键分享。单选模式更适合社交分享,选一个目标App就行。

写在最后

Share Kit 把"分享"这件事从一团乱麻变成了几行代码的事。UTD 统一数据类型、标准化的发送接收协议、配置驱动的面板注册——这套组合拳真的省心。

我自己的感受是:以前适配分享至少得折腾半天,现在半小时搞定。尤其是接收端的配置,只要 module.json5 写对了,剩下的都是标准流程。

如果你还在用隐式 Intent 做分享,赶紧换 Share Kit 吧,真的不一样。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐