大家好,我是陈杨,8 年前端老兵转型鸿蒙开发,也是一名鸿蒙极客。从前端到鸿蒙,我靠的是 “三天上手 ArkTS” 的技术嗅觉,以及 “居安思危” 的转型魄力。这三年,我不玩虚的,封装了开源组件库「莓创图表」,拿过创新赛大奖,更带着团队上架了 11 款自研 APP,涵盖工具、效率、创意等多个领域。想体验我的作品?欢迎搜索体验:指令魔方、JLPT、REFLEX PRO、国潮纸刻、Wss 直连、ZenithDocs Pro、圣诞相册、CSS 特效

在上一篇文章中,我们掌握了 Share Kit 的基础用法和跨端分享核心场景。但在实际开发中,不同应用对分享功能的需求差异显著:有的需要自定义分享面板样式,有的需要限制分享目标范围(如企业内部应用),还有的需要统计分享渠道数据。本文将聚焦 Share Kit 的进阶能力,结合全接/半接接入模式、操作区自定义、企业级权限控制等场景,带大家实现更灵活、更贴合业务需求的分享功能。

一、宿主应用接入模式:全接 vs 半接

Share Kit 提供两种接入模式,分别适配不同开发诉求,我们可根据业务场景选择:

1.1 两种接入模式对比

接入模式 核心特点 适用场景 开发成本
全接模式 直接使用系统默认分享面板,无需自定义 UI 华为自研应用、对分享面板无商业诉求的普通应用(如工具类 App) 低(无需开发面板,调用接口即可)
半接模式 我们自定义分享面板,同时保留系统分享入口 有商业推广需求(如优先展示自家应用)、需要独特业务逻辑(如分享前添加水印)的应用 中(需开发自定义面板,集成系统分享入口)

1.2 全接模式实战(快速接入)

全接模式是最常用的接入方式,直接复用系统分享面板,适合快速实现分享功能。以下是多类型内容(文本+图片)分享的完整示例:

核心代码实现
import { systemShare } from '@kit.ShareKit';
import { uniformTypeDescriptor as utd } from '@kit.ArkData';
import { common, BusinessError } from '@kit.AbilityKit';
import { fileUri } from '@kit.CoreFileKit';
import promptAction from '@ohos.promptAction';

// 全接模式:分享文本+图片组合内容
async function fullAccessShare() {
  try {
    // 1. 获取应用沙箱路径(用于图片存储)
    const uiContext = this.getUIContext();
    const context = uiContext.getHostContext() as common.UIAbilityContext;
    const imagePath = `${context.cacheDir}/combined_image.png`; // 假设图片已保存到沙箱

    // 2. 构造分享数据(支持多记录组合)
    const shareData = new systemShare.SharedData({
      utd: utd.UniformDataType.PLAIN_TEXT, // 文本类型
      content: '这是一条组合分享内容',
      title: '组合分享示例'
    });

    // 3. 添加图片分享记录(多内容分享)
    shareData.addRecord({
      utd: utd.UniformDataType.PNG, // 图片类型
      uri: fileUri.getUriFromPath(imagePath), // 图片 URI
      thumbnailUri: fileUri.getUriFromPath(imagePath) // 缩略图
    });

    // 4. 构建分享控制器并显示系统面板
    const controller = new systemShare.ShareController(shareData);

    // 注册面板关闭监听
    controller.on('dismiss', () => {
      console.info('系统分享面板已关闭');
    });

    // 显示分享面板(默认样式)
    await controller.show(context, {
      previewMode: systemShare.SharePreviewMode.DETAIL, // 详细预览模式
      selectionMode: systemShare.SelectionMode.SINGLE // 单选模式
    });
  } catch (error) {
    const err = error as BusinessError;
    console.error(`全接模式分享失败:Code=${err.code}, Message=${err.message}`);
    promptAction.showToast({ message: '分享失败,请重试' });
  }
}
关键说明
  • 多内容分享:通过 addRecord() 方法可添加多个不同类型的分享内容(如文本+图片、多图片),系统面板会自动适配预览样式。
  • 预览模式:SharePreviewMode.DETAIL 会显示完整的内容预览(如图片大图+文本全文),DEFAULT 则显示简化预览。

1.3 半接模式实战(自定义面板+系统入口)

半接模式允许我们自定义分享面板,同时提供系统分享入口,兼顾业务个性化和生态兼容性。核心要求:系统分享入口的图标和文本必须使用系统资源,不可自定义。

步骤 1:自定义分享面板 UI(ArkUI)
import { Button, Column, Text, SymbolGlyph, Flex } from '@kit.ArkUI';
import { systemShare } from '@kit.ShareKit';

@Component
struct CustomSharePanel {
  // 自定义分享回调(如分享到自家应用)
  private onCustomShare(type: string) {
    console.info(`分享到${type}`);
    // 自定义分享逻辑(如跳转到自家应用的分享页面)
  }

  // 打开系统分享面板
  private openSystemShare() {
    // 此处调用系统分享接口(同全接模式的核心逻辑)
    this.fullAccessShare();
  }

  build() {
    Column({ space: 15 }) {
      // 自定义分享选项
      Button('分享到我的应用')
        .width('100%')
        .height(45)
        .onClick(() => this.onCustomShare('我的应用'));

      Button('分享到朋友圈')
        .width('100%')
        .height(45)
        .onClick(() => this.onCustomShare('朋友圈'));

      // 系统分享入口(必须使用系统图标和文本)
      Button(
        Flex({ alignItems: 'center', justifyContent: 'center', space: 8 }) {
          // 系统分享图标(不可自定义)
          SymbolGlyph($r('sys.symbol.share'))
            .width(20)
            .height(20);
          // 系统分享文本(不可自定义)
          Text('系统分享')
            .fontSize(16);
        }
      )
        .width('100%')
        .height(45)
        .backgroundColor('#F5F5F5')
        .onClick(() => this.openSystemShare());
    }
    .padding(20)
    .width(300)
  }

  // 此处引入全接模式的 fullAccessShare 方法
}
步骤 2:在页面中弹出自定义面板
@Component
struct HomePage {
  @State isSharePanelShow: boolean = false;

  build() {
    Column({ space: 20 }) {
      Button('打开自定义分享面板')
        .width(250)
        .height(45)
        .onClick(() => {
          this.isSharePanelShow = true;
        });

      // 自定义分享面板(模态弹窗)
      if (this.isSharePanelShow) {
        ModalDialog({
          confirm: () => this.isSharePanelShow = false,
          cancel: () => this.isSharePanelShow = false,
          showCancel: false
        }) {
          CustomSharePanel();
        }
        .width('80%')
        .height('auto');
      }
    }
    .padding(20)
    .width('100%')
    .justifyContent('center');
  }
}
关键规范
  • 系统分享入口必须使用 $r('sys.symbol.share') 图标和“系统分享”文本,否则会影响应用上架审核。
  • 自定义面板需保证操作流程简洁,避免过度复杂的业务逻辑(如分享前强制观看广告),影响用户体验。

二、分享面板个性化配置

Share Kit 支持对分享面板的预览模式、操作区、显示位置等进行精细化配置,满足不同设备和业务场景的需求。

2.1 配置 2in1 设备分享面板位置

2in1 设备(如折叠屏、平板)支持通过 anchor 参数配置分享面板的显示位置,适配大屏操作习惯:

// 2in1 设备分享面板位置配置
function configure2in1SharePosition() {
  const uiContext = this.getUIContext();
  const context = uiContext.getHostContext() as common.UIAbilityContext;

  // 构造分享数据(文本类型)
  const shareData = new systemShare.SharedData({
    utd: utd.UniformDataType.PLAIN_TEXT,
    content: '2in1 设备分享示例'
  });

  const controller = new systemShare.ShareController(shareData);

  // 方式一:关联控件 ID(面板显示在指定控件下方)
  controller.show(context, {
    anchor: 'shareButton', // 与 UI 中 button 的 id 对应
    previewMode: systemShare.SharePreviewMode.DEFAULT
  });

  // 方式二:指定坐标(绝对位置显示)
  // controller.show(context, {
  //   anchor: {
  //     windowOffset: { x: 200, y: 300 }, // 相对于屏幕左上角的偏移量
  //     size: { width: 0, height: 0 } // 组件大小(可选,用于计算对齐方式)
  //   },
  //   previewMode: systemShare.SharePreviewMode.DEFAULT
  // });
}

2.2 自定义操作区(隐藏不需要的系统功能)

系统操作区默认提供复制、保存、打印、添加到中转站等功能,宿主应用可通过 excludedAbilities 参数隐藏不需要的操作:

// 自定义操作区:隐藏打印功能
function customizeShareOperations() {
  const uiContext = this.getUIContext();
  const context = uiContext.getHostContext() as common.UIAbilityContext;

  // 构造图片分享数据
  const imagePath = `${context.cacheDir}/example.jpg`;
  const shareData = new systemShare.SharedData({
    utd: utd.UniformDataType.IMAGE,
    uri: fileUri.getUriFromPath(imagePath),
    title: '自定义操作区示例'
  });

  const controller = new systemShare.ShareController(shareData);

  // 注册面板关闭监听
  controller.on('dismiss', () => {
    console.info('分享面板关闭,清理临时资源');
  });

  // 显示面板并隐藏打印功能
  controller.show(context, {
    previewMode: systemShare.SharePreviewMode.DETAIL,
    selectionMode: systemShare.SelectionMode.SINGLE,
    excludedAbilities: [systemShare.ShareAbilityType.PRINT] // 隐藏打印操作
  });
}
支持隐藏的系统操作类型
操作类型 说明
PRINT 打印功能
COPY 复制功能
SAVE 保存功能
SAVE_AS 另存为功能
ADD_TO_TRANSIT_STATION 添加到中转站功能

2.3 获取分享结果(统计分享渠道)

我们可通过 shareCompleted 事件监听用户的分享行为,获取分享目标渠道信息,用于数据统计(如哪种分享渠道使用率最高):

// 获取分享结果,统计分享渠道
function getShareResult() {
  const uiContext = this.getUIContext();
  const context = uiContext.getHostContext() as common.UIAbilityContext;

  const shareData = new systemShare.SharedData({
    utd: utd.UniformDataType.PLAIN_TEXT,
    content: '分享结果统计示例'
  });

  const controller = new systemShare.ShareController(shareData);

  // 注册分享结果监听
  controller.on('shareCompleted', (result: systemShare.ShareOperationResult) => {
    const targetName = result.targetAbilityInfo.name;
    console.info(`用户分享到:${targetName}`);

    // 统计逻辑:如上传到后台服务器
    // reportShareChannel(targetName);

    // 渠道名称规则:
    // 1. 系统操作(如复制):固定名称(参考 ShareAbilityName)
    // 2. 第三方应用:格式为 "[bundleName]#[moduleName]#[abilityName]"
  });

  controller.show(context, {
    previewMode: systemShare.SharePreviewMode.DEFAULT
  });
}
渠道名称解析示例
  • 系统操作“复制”:ohos.system.share.ability.copy
  • 微信分享:com.tencent.mm#module_main#WeChatShareAbility

三、企业级功能:限制分享目标应用名单

对于企业应用,往往需要限制内部数据只能分享到企业信任的应用(如集团内部 App),避免数据泄露。Share Kit 提供了目标应用名单配置功能,仅对企业应用开放。

3.1 前置条件

  1. 权限申请:需要申请受限权限 ohos.permission.SET_SYSTEMSHARE_APPLAUNCHTRUSTLIST,申请时需说明企业信息和管控场景(如“用于 XX 集团内部资料仅分享给集团应用”)。
  2. 应用类型:仅企业应用支持该功能,普通我们应用无法使用。

3.2 完整实现步骤

步骤 1:在 module.json5 中声明权限
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.SET_SYSTEMSHARE_APPLAUNCHTRUSTLIST",
        "reason": "$string:permission_reason", // 权限申请理由(需填写企业管控场景)
        "usedScene": {
          "ability": ["com.example.enterprise.ShareAbility"],
          "when": "always"
        }
      }
    ]
  }
}
步骤 2:配置目标应用名单

通过 appLaunchTrustInfo 参数指定允许分享的应用 AppIdentifier(可在华为我们联盟后台查询应用的 AppIdentifier):

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

@Component
export struct EnterpriseSharePage {
  build() {
    Button('企业内部分享')
      .onClick(() => this.enterpriseRestrictedShare());
  }

  private enterpriseRestrictedShare() {
    // 1. 构造分享数据(企业内部文档)
    const shareData = new systemShare.SharedData({
      utd: utd.UniformDataType.DOCUMENT,
      uri: 'file:///data/storage/el2/base/cache/enterprise_doc.pdf',
      title: '企业内部文档'
    });

    // 2. 获取上下文
    const uiContext = this.getUIContext();
    const context = uiContext.getHostContext() as common.UIAbilityContext;

    // 3. 构建控制器并配置信任应用名单
    const controller = new systemShare.ShareController(shareData);
    controller.show(context, {
      previewMode: systemShare.SharePreviewMode.DEFAULT,
      selectionMode: systemShare.SelectionMode.SINGLE,
      // 目标应用 AppIdentifier 列表(最多支持 50 个)
      appLaunchTrustInfo: [
        '5765880207853060000', // 企业应用 A 的 AppIdentifier
        '1171817433862770000'  // 企业应用 B 的 AppIdentifier
      ]
    });
  }
}
关键说明
  • AppIdentifier 是应用的唯一标识,需从华为我们联盟后台“应用信息”中查询,不可随意填写。
  • 配置后,系统分享面板仅显示名单内的应用,其他应用不会出现在推荐区和分享方式区。
  • 该功能仅限制分享目标,不影响分享数据的传输安全性,企业需额外确保数据本身的加密(如文档加密)。

四、多场景分享示例:App Linking 直达应用

除了文本、图片等基础类型,Share Kit 还支持分享 App Linking 链接,用户点击后可直达应用指定页面(如商品详情页),提升转化效率。

4.1 核心原理

  • App Linking 是 HarmonyOS 提供的深度链接服务,支持跨应用跳转。
  • 分享 App Linking 时,目标设备接收后会自动打开对应的应用(如未安装则拉起应用市场)。

4.2 完整代码实现

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

// 分享 App Linking 直达应用页面
function shareAppLinking() {
  const uiContext = this.getUIContext();
  const context = uiContext.getHostContext() as common.UIAbilityContext;

  // 1. 构造 App Linking 分享数据(需先通过 App Linking 服务生成链接)
  const appLinking = 'https://applinking.huawei.com/abc123?page=productDetail&id=10086';
  const shareData = new systemShare.SharedData({
    utd: utd.UniformDataType.APP_LINKING, // App Linking 类型
    content: appLinking,
    title: '点击查看商品详情',
    description: '直达华为商城商品页面'
  });

  const controller = new systemShare.ShareController(shareData);

  // 2. 显示分享面板
  controller.show(context, {
    previewMode: systemShare.SharePreviewMode.DEFAULT,
    selectionMode: systemShare.SelectionMode.SINGLE
  });

  // 3. 监听分享结果
  controller.on('shareCompleted', (result) => {
    console.info(`App Linking 分享到:${result.targetAbilityInfo.name}`);
  });
}
接收端处理逻辑

目标设备接收后,会按照以下规则处理:

  1. 若已安装对应应用:直接打开应用并跳转到 page=productDetail&id=10086 对应的页面。
  2. 若未安装应用:拉起华为应用市场,展示该应用的下载页面(需在 App Linking 配置中关联应用)。
  3. 若为 PC/2in1 设备:通过浏览器打开链接(如应用支持 PC 端,可跳转至 PC 应用)。

五、常见问题与进阶技巧

5.1 常见问题排查

问题场景 可能原因 解决方案
企业应用无法配置目标应用名单 1. 未申请受限权限 2. 权限申请理由未说明企业管控场景 1. 在 module.json5 中声明权限 2. 重新提交权限申请,详细描述企业名称、管控场景(如“内部资料防泄露”)
2in1 设备分享面板位置异常 anchor 参数配置错误(如控件 ID 不存在、坐标超出屏幕范围) 1. 确保 anchor 对应的控件 ID 在 UI 中存在 2. 坐标值需根据设备屏幕尺寸动态计算(避免硬编码)
分享 App Linking 无法跳转应用 1. App Linking 未正确关联应用 2. 目标设备未安装应用且未配置应用市场跳转 1. 在华为我们联盟后台配置 App Linking 与应用的关联关系 2. 检查 App Linking 生成时的跳转规则配置

5.2 进阶技巧

  1. 分享数据加密:对于敏感数据(如企业文档),分享前可通过 AES 加密,目标应用接收后解密,提升数据安全性。
  2. 多语言适配:分享面板的标题、描述需支持多语言,可通过 $string: 资源引用实现(如 title: $r('app.string.share_title'))。
  3. 性能优化:分享多张大图时,先压缩图片(建议单张图片小于 5MB),避免分享数据超过 200KB 限制。
  4. 兼容性处理:通过 deviceInfo 模块判断设备类型(如 TV、平板),针对性调整分享面板配置(如 TV 设备仅支持分享到周边设备)。

六、总结

本文聚焦 Share Kit 的进阶能力,覆盖了接入模式选择、面板个性化配置、企业级权限控制、App Linking 分享等核心场景,关键要点总结如下:

  1. 接入模式:全接模式快速实现,半接模式支持自定义,根据业务诉求选择。
  2. 个性化配置:支持隐藏系统操作、配置面板位置、获取分享结果,适配不同设备和业务需求。
  3. 企业级功能:通过受限权限配置目标应用名单,保障内部数据安全(仅企业应用支持)。
  4. 场景扩展:App Linking 分享支持直达应用页面,提升用户转化效率。

Share Kit 的核心优势在于“统一接口+灵活扩展”,我们无需关注跨应用、跨设备的底层通信细节,只需通过简单配置即可实现复杂的分享功能。如需进一步深入,可参考华为我们文档的 Share Kit 进阶指南,探索更多高级特性(如自定义分享预览样式、多设备协同分享)。

通过本文的实战案例,相信大家已能应对大多数业务场景的分享需求。在实际开发中,建议结合应用的核心场景(如普通工具类应用用全接模式,企业应用用名单限制),灵活组合 Share Kit 的各项能力,打造更优质的用户体验。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐