当前位置: 首页 > news >正文

HarmonyOS APP《画伴梦工厂》开发第30篇-跨设备分享——systemShare集成

第4.4篇:跨设备分享——systemShare 集成

难度:⭐⭐ 进阶
前置知识:第 2.9 篇 视频导出与本地保存
涉及源文件products/default/src/main/ets/services/VideoExportService.ets


概述

在"画伴梦工厂"中,用户创作完成动画视频后,不仅仅希望保存到本地——更希望能与家人、朋友分享,甚至发送到其他设备上观看。HarmonyOS 提供了systemShare(系统分享)能力,通过标准化的分享面板,让应用可以将内容分享到其他应用或跨设备传输。

systemShare@kit.ShareKit中的核心模块,它封装了系统级的分享服务,支持视频、图片、文本等多种数据类型,并且天然具备跨设备分享能力——用户可以将内容一键分享到同一华为账号下的平板、智慧屏、手机等其他设备。

本文将深入解析systemShare在项目中的完整集成实践,涵盖ShareController创建与配置、SharedData多记录数据构建、uniformTypeDescriptor类型描述、以及跨设备分享的实际应用场景。


一、systemShare 整体架构

1.1 核心类与接口

systemShare模块围绕三个核心概念构建:

类/接口说明
systemShare.ShareController分享控制器,负责展示系统分享面板并管理分享流程
systemShare.SharedData分享数据容器,可包含一条或多条分享记录
systemShare.ShareControllerOptions分享控制选项,配置选择模式和预览模式
systemShare.SelectionMode选择模式枚举:SINGLE(单选应用)、MULTIPLE(多选应用)
systemShare.SharePreviewMode预览模式枚举:DETAIL(详细预览)、SUMMARY(概览预览)

1.2 分享流程概览

用户点击"分享"按钮 │ ▼ prepareVideo() → 准备视频文件(缓存目录) │ ▼ buildSharedData() → 构建分享数据(视频 + 文本) │ ▼ new ShareController(data) → 创建分享控制器 │ ▼ controller.show(context, options) → 弹出系统分享面板 │ ├──→ 用户选择目标应用 → 执行分享 │ └──→ 用户取消 → 静默结束

整个过程仅需四个步骤——准备文件、构建数据、创建控制器、调用 show 方法——即可完成一次完整的系统分享。


二、ShareController:分享控制器

2.1 创建 ShareController

ShareController是分享流程的入口,其构造函数接收一个SharedData实例:

constdata=awaitVideoExportService.buildSharedData(videoUri,title,story,rawFilePath);constcontroller=newsystemShare.ShareController(data);

ShareController实例化后,会立即解析SharedData中的记录信息,准备展示分享面板。

2.2 启动分享面板

constoptions:systemShare.ShareControllerOptions={selectionMode:systemShare.SelectionMode.SINGLE,previewMode:systemShare.SharePreviewMode.DETAIL};awaitcontroller.show(context,options);

show方法接收两个参数:

  1. contextUIAbilityContext实例,用于获取当前页面的上下文环境。
  2. optionsShareControllerOptions配置对象,控制分享面板的行为和外观。

show是一个异步方法,返回Promise<void>。当用户选择目标应用完成分享或取消操作时,Promise 会 resolve。

注意ShareController实例为一次性使用。每次分享都需要重新创建ShareControllerSharedData


三、ShareControllerOptions 配置详解

ShareControllerOptions提供了两个关键的配置项,分别控制分享应用的选择方式和预览界面的展示形态。

3.1 selectionMode:选择模式

selectionMode:systemShare.SelectionMode.SINGLE
枚举值说明适用场景
SelectionMode.SINGLE单次选择模式,用户一次只能选择一个目标应用快速分享给单个好友或设备
SelectionMode.MULTIPLE多选模式,用户可以选择多个目标应用同时分享同时分享到多个社交平台

在"画伴梦工厂"中,我们使用SINGLE模式。对于儿童动画视频的分享场景,通常用户只会将视频分享给特定的联系人(如家人)或发送到特定的设备(如智慧屏),单次选择模式更符合直觉。

3.2 previewMode:预览模式

previewMode:systemShare.SharePreviewMode.DETAIL
枚举值说明效果
SharePreviewMode.DETAIL详细预览模式分享面板中会显示分享内容的详细预览信息(缩略图、标题、描述)
SharePreviewMode.SUMMARY概览预览模式仅显示简洁的分享概览信息

项目中选择了DETAIL模式。当用户分享动画视频时,详细预览可以让用户在发送前确认视频的标题和故事描述是否正确,提供更好的用户体验。

3.3 配置组合效果

DETAIL + SINGLE: ┌─────────────────────────────────────┐ │ 系统分享面板 │ │ ┌──────────────────────────────┐ │ │ │ 🎬 我的小汽车 │ │ │ │ 一辆红色的小汽车在公路上... │ │ │ │ [视频缩略图] │ │ │ └──────────────────────────────┘ │ │ │ │ 选择应用: │ │ [微信] [钉钉] [智慧屏] [蓝牙] │ │ │ └─────────────────────────────────────┘

四、SharedData:构建分享数据

4.1 多记录数据模型

systemShare.SharedData支持包含多条记录,每条记录可以有不同的数据类型。在项目中,我们构建了视频记录和文本记录两条数据:

staticasyncbuildSharedData(videoUri:Resource|string,title:string,story:string,rawFilePath:string):Promise<systemShare.SharedData>{constprepared=awaitVideoExportService.prepareVideo(videoUri,title,rawFilePath);// 视频记录constvideoRecord:ShareVideoRecord={utd:uniformTypeDescriptor.UniformDataType.MPEG4,uri:prepared.uri,title:title,description:story};constdata=newsystemShare.SharedData(videoRecord);// 文本记录(添加为次要记录)consttextRecord:ShareTextRecord={utd:uniformTypeDescriptor.UniformDataType.PLAIN_TEXT,content:title+'\n'+story,title:title,description:story};data.addRecord(textRecord);returndata;}

4.2 记录类型接口

项目中定义了两个分享记录接口:

interfaceShareVideoRecord{utd:string;// Uniform Type Descriptor,标识数据类型uri:string;// 视频文件的 URItitle:string;// 作品标题description:string;// 作品故事描述}interfaceShareTextRecord{utd:string;// 数据类型标识content:string;// 文本内容title:string;// 标题description:string;// 描述}

4.3 记录添加机制

  • 主记录:通过new systemShare.SharedData(primaryRecord)在构造函数中指定。
  • 次要记录:通过data.addRecord(record)方法动态添加,支持添加多条。

当系统分享面板接收到包含多条记录的SharedData时,会根据目标应用的能力自动选择合适的记录进行分享。例如:

目标应用行为
微信/钉钉同时展示视频和文本,用户可选择发送
智慧屏/电视优先分享视频记录,忽略文本记录
备忘录/笔记优先分享文本记录,视频作为附件
蓝牙传输传输视频文件,文本作为文件描述

这种"多条记录、按需选择"的机制,使得一次分享可以适配多种不同类型的目标应用。


五、uniformTypeDescriptor:统一类型描述

5.1 什么是 UTD?

uniformTypeDescriptor(Uniform Type Descriptor,统一类型描述符)是 HarmonyOS 中用于标识文件和数据类型的标准化描述体系。它类似于 MIME 类型,但更加精细和层次化。

@kit.ArkData中的uniformTypeDescriptor模块预定义了系统中常见的标准数据类型:

常量对应类型说明
UniformDataType.MPEG4视频MPEG-4 视频格式(.mp4)
UniformDataType.PLAIN_TEXT文本纯文本格式
UniformDataType.JPEG图片JPEG 图片格式
UniformDataType.PNG图片PNG 图片格式
UniformDataType.MP3音频MP3 音频格式
UniformDataType.PDF文档PDF 文档格式

5.2 UTD 在分享中的作用

在 systemShare 中,每条分享记录都必须指定utd字段,其作用包括:

  1. 应用匹配:系统根据 UTD 类型筛选出能够处理该类型数据的目标应用。
  2. 格式识别:目标应用通过 UTD 了解收到的数据类型,选择合适的处理方式。
  3. 预览展示:系统分享面板根据 UTD 决定如何展示预览内容(视频缩略图、文本摘要等)。

5.3 项目中 UTD 的使用

import{uniformTypeDescriptor}from'@kit.ArkData';// 视频记录使用 MPEG4 类型constvideoRecord:ShareVideoRecord={utd:uniformTypeDescriptor.UniformDataType.MPEG4,// ...};// 文本记录使用 PLAIN_TEXT 类型consttextRecord:ShareTextRecord={utd:uniformTypeDescriptor.UniformDataType.PLAIN_TEXT,// ...};

选择正确的 UTD 类型至关重要——如果视频记录错误地使用PLAIN_TEXT,系统分享面板将无法正确识别文件格式,目标应用也无法正常打开分享内容。


六、完整分享流程:从准备到展示

6.1 视频准备

分享的第一步是确保视频文件在本地可访问。prepareVideo方法处理了两种场景:

constprepared=awaitVideoExportService.prepareVideo(videoUri,title,rawFilePath);
  • Resource(rawfile 资源):通过resourceManager.getRawFileContent读取内置视频,写入应用缓存目录。
  • string(本地路径):校验路径有效性,直接使用现有文件。

具体细节已在第 2.9 篇中详细讲解,此处不再赘述。

6.2 数据构建

buildSharedData方法接收四个参数:

参数类型说明
videoUriResource | string视频文件资源或路径
titlestring作品标题
storystring作品故事描述
rawFilePathstringrawfile 中的视频路径(仅 Resource 类型需要)

方法内部依次完成:准备视频 → 创建视频记录 → 实例化 SharedData → 添加文本记录。

6.3 展示分享面板

constcontext=getContext()ascommon.UIAbilityContext;constcontroller=newsystemShare.ShareController(data);constoptions:systemShare.ShareControllerOptions={selectionMode:systemShare.SelectionMode.SINGLE,previewMode:systemShare.SharePreviewMode.DETAIL};awaitcontroller.show(context,options);

controller.show调用后,系统会弹出分享面板,用户完成选择或取消后,Promise resolve。

6.4 完整流程时序图

VideoExportService.showSystemShare() │ ├── prepareVideo(videoUri, title, rawFilePath) │ ├── typeof videoUri === 'string' → 直接使用本地文件 │ └── typeof videoUri === 'Resource' → 读取 rawfile → 写入 cacheDir │ └── 返回 PreparedVideoFile { path, uri, fileName } │ ├── buildSharedData(videoUri, title, story, rawFilePath) │ ├── 调用 prepareVideo() 获取 prepared │ ├── 创建 ShareVideoRecord { utd: MPEG4, uri, title, description } │ ├── new SharedData(videoRecord) ← 主记录 │ ├── 创建 ShareTextRecord { utd: PLAIN_TEXT, content, title, description } │ └── data.addRecord(textRecord) ← 添加次要记录 │ ├── new ShareController(data) │ └── controller.show(context, { selectionMode: SINGLE, previewMode: DETAIL }) │ ├── 用户选择应用 → 分享成功 │ └── 用户取消 → 流程结束

七、与 UI 层集成

在 Index.ets 页面中,分享功能通过shareCurrentVideo方法触发:

privateasyncshareCurrentVideo():Promise<void>{if(this.exportBusy){return;}this.exportBusy=true;this.showNotice('正在打开分享');try{awaitVideoExportService.showSystemShare(this.getCurrentVideo(),this.getCurrentWorkTitle(),this.getCurrentWorkStory(),this.getCurrentRawVideoPath());this.sharedActive=true;this.showNotice('已打开分享面板');}catch(error){this.showNotice('分享失败:'+this.getErrorMessage(errorasError));}finally{this.exportBusy=false;}}

设计要点

1. 防重复操作锁

exportBusy是一个@State布尔变量,用于防止用户在分享进行中重复点击:

if(this.exportBusy){return;// 正在分享中,忽略重复请求}

2. 用户反馈

分享过程中通过showNotice显示状态提示文字:

  • “正在打开分享” → 用户操作触发后立即提示
  • “已打开分享面板” → 分享面板成功弹出后提示
  • “分享失败:xxx” → 发生异常时提示错误原因

3. try/catch/finally 资源清理

try{// 执行分享}catch(error){// 异常处理}finally{this.exportBusy=false;// 无论成功失败,最终释放锁}

这种模式确保exportBusy在任何情况下都能正确释放,不会出现"死锁"状态。


八、跨设备分享场景

systemShare 的跨设备能力是其核心价值之一。当用户在同一华为账号下拥有多台设备时,系统分享面板会自动发现并列出可用的跨设备目标。

8.1 手机 → 平板

场景:孩子在手机上用"画伴梦工厂"制作了一段动画,想在大屏平板上全屏观看。

流程

  1. 点击"分享"按钮 → 系统弹出分享面板
  2. 分享面板自动显示同一华为账号下的平板设备
  3. 选择平板 → 视频通过分布式软总线传输到平板
  4. 平板上打开视频,大屏观看体验更佳

8.2 手机 → 智慧屏

场景:家庭聚会时,孩子想把自己创作的动画展示在电视上。

流程

  1. 点击"分享" → 分享面板显示智慧屏设备
  2. 选择智慧屏 → 视频传输到电视
  3. 电视播放动画,全家一起观看

8.3 手机 → 其他应用

场景:将视频分享到微信、钉钉等社交应用。

流程

  1. 点击"分享" → 分享面板显示已安装的社交应用
  2. 选择微信 → 系统将视频和文本描述一起发送到微信
  3. 在微信中选择联系人发送

8.4 跨设备分享的技术基础

systemShare 的跨设备能力依赖于 HarmonyOS 的分布式软总线技术:

  • 设备发现:自动发现同一华为账号下的在线设备
  • 安全传输:端到端加密,保障数据传输安全
  • 类型适配:目标设备根据 UTD 类型自动匹配处理方式
  • 无缝体验:用户无需手动配对或配置

九、systemShare vs. 其他分享方式

9.1 与 DocumentViewPicker 的对比

维度systemShareDocumentViewPicker
核心功能分享到其他应用/设备保存到本地文件系统
数据流向发送出去保存到本地
跨设备✅ 天然支持❌ 仅本地保存
数据类型视频、文本、图片等多类型主要是文件
用户交互选择目标应用选择保存位置
使用场景分享给好友、发送到其他设备备份到本地、导出到电脑

9.2 与 startAbilityForResult 的对比

startAbilityForResult也可以启动其他应用,但它是"定向启动"——开发者必须预先知道目标应用的 Ability 信息。而systemShare是"系统级分发"——由用户自由选择目标,开发者只需提供数据即可。

// startAbilityForResult:定向启动awaitcontext.startAbilityForResult({bundleName:'com.example.target',abilityName:'TargetAbility'});// systemShare:系统分发awaitcontroller.show(context,options);

十、最佳实践与注意事项

10.1 数据容量考虑

  • 分享数据不宜过大。大文件分享建议先压缩或提供下载链接。
  • 文本记录内容长度适中,过长的描述可能在某些应用中显示不全。

10.2 UTD 类型准确性

  • 务必为每条记录指定正确的 UTD 类型,否则目标应用可能无法识别数据。
  • 常见的视频类型使用UniformDataType.MPEG4,图片使用UniformDataType.JPEGUniformDataType.PNG

10.3 上下文生命周期

  • context必须是有效的UIAbilityContext,不能使用已销毁的页面上下文。
  • 建议在调用分享前检查上下文状态,避免分享面板弹出时页面已关闭。

10.4 资源清理

  • ShareController实例不使用时无需手动销毁,系统会自动管理。
  • 缓存目录中的临时视频文件可以在适当时机清理,避免占用过多存储空间。

10.5 用户隐私

  • 分享内容中不应包含用户敏感信息。
  • 项目中的文本记录仅包含作品标题和故事,不包含用户个人信息。

十一、完整代码总览

最终,VideoExportService 中与分享相关的完整代码如下:

// 展示系统分享面板staticasyncshowSystemShare(videoUri:Resource|string,title:string,story:string,rawFilePath:string):Promise<void>{constcontext=getContext()ascommon.UIAbilityContext;constdata=awaitVideoExportService.buildSharedData(videoUri,title,story,rawFilePath);constcontroller=newsystemShare.ShareController(data);constoptions:systemShare.ShareControllerOptions={selectionMode:systemShare.SelectionMode.SINGLE,previewMode:systemShare.SharePreviewMode.DETAIL};awaitcontroller.show(context,options);}// 构建分享数据staticasyncbuildSharedData(videoUri:Resource|string,title:string,story:string,rawFilePath:string):Promise<systemShare.SharedData>{constprepared=awaitVideoExportService.prepareVideo(videoUri,title,rawFilePath);constvideoRecord:ShareVideoRecord={utd:uniformTypeDescriptor.UniformDataType.MPEG4,uri:prepared.uri,title:title,description:story};constdata=newsystemShare.SharedData(videoRecord);consttextRecord:ShareTextRecord={utd:uniformTypeDescriptor.UniformDataType.PLAIN_TEXT,content:title+'\n'+story,title:title,description:story};data.addRecord(textRecord);returndata;}

总结

本文深入讲解了 HarmonyOS systemShare 在"画伴梦工厂"中的完整集成实践:

知识点说明
ShareController分享控制器,通过构造函数传入 SharedData,调用 show 弹出分享面板
ShareControllerOptions配置 selectionMode(单选/多选)和 previewMode(详细/概览预览)
SharedData 多记录支持主记录 + 多条次要记录,不同目标应用按需选择
uniformTypeDescriptor统一类型描述,标识数据格式,影响应用匹配和预览展示
分享流程prepareVideo → buildSharedData → new ShareController → show
防重复操作exportBusy 状态锁 + try/catch/finally 资源释放
跨设备分享手机 → 平板/智慧屏/社交应用,基于分布式软总线自动发现设备

systemShare的精妙之处在于其"一次集成、处处可用"的设计理念——开发者只需构建数据、弹出面板,系统负责应用的匹配、数据的传输、跨设备的协同。这种设计让应用能够以极低的成本获得强大的分享能力,也是 HarmonyOS 全场景智慧体验的典型体现。


参考源码

本文所有代码均来自项目文件:

  • products/default/src/main/ets/services/VideoExportService.ets— 视频导出服务的完整实现,包含 systemShare 分享、DocumentViewPicker 保存、文件操作等核心方法
http://www.gsyq.cn/news/1623697.html

相关文章:

  • 机械臂视觉标定工具包:兼容大恒/IDS uEye/USB工业相机,支持手眼标定全流程
  • Mac风扇控制终极指南:如何用smcFanControl解决Intel Mac发烫问题?
  • Web自动化验证码破解:打码平台集成实战与优化策略
  • Playwright自动化测试从录制到Jenkins集成的完整实践指南
  • 认知即资产:WSaiOS Marketplace 的设计哲学与技术架构
  • 夸克网盘自动转存终极指南:彻底告别手动转存的繁琐操作
  • GetQzonehistory终极指南:如何用Python一键找回所有QQ空间记忆
  • Selenium+Pytest+POM:构建稳定可维护的Web UI自动化测试框架实战
  • Playwright+Pillow实现UI自动化测试中的像素级视觉验证
  • Open-AutoGLM:AI驱动的UI自动化测试框架实战解析
  • 企业级API安全实战:基于OWASP标准构建全链路防御体系
  • 如何在Blender中实现3MF格式的完整支持:3D打印工作流的终极解决方案
  • RASP技术实战:深度解析SQL注入误报成因与分层优化策略
  • Java+Selenium+Cucumber自动化测试框架:构建可维护的BDD测试体系
  • 前端密码加密实战:从哈希到混合加密的纵深防御方案
  • WebdriverIO+Cucumber测试状态管理:构建强类型上下文与场景隔离方案
  • 流放之路2角色构建终极指南:免费开源工具Path of Building PoE2
  • 猫抓插件终极指南:免费开源的一站式浏览器资源嗅探解决方案
  • JMeter中利用Groovy脚本实现SSE流式接口测试与数据实时解析
  • 基于Playwright与Java的UI自动化测试框架设计与实战
  • 海上钢琴师观后感:那些留在心里的片刻
  • 监控视频流里实时揪出烟雾的Python小工具(带预处理和轻量CNN)
  • 3种专业方案彻底清理Windows系统组件:EdgeRemover高效卸载工具完整指南
  • Java写的本地银行桌面程序:带图形界面、MD5加密登录、转账校验和配置文件存数据
  • Fortify SCA 24.2.0实战:构建高效自动化代码审计与CI/CD集成流水线
  • 告别版本混乱!智能文档管理如何赋能多人在线协同编辑?
  • 构建三重防护行为验证码系统:从原理到工程实践
  • 量子加密通信在元宇宙数据传输中的四步工程实践
  • Playwright测试结果实时通知Slack:自动化测试与团队协作的工程实践
  • ai模特图电商快速生成与精细处理方案解析