HarmonyOS社交通讯应用开发17: 跨设备拉取媒体(CollaborationService)

发布时间:2026/8/25 22:35:41

HarmonyOS社交通讯应用开发17: 跨设备拉取媒体(CollaborationService)
跨设备拉取媒体CollaborationService引言上一篇我们看了从本机相册选图这一篇升级到跨设备用户手机上没有合适的图片能不能直接从平板、电脑甚至另一台手机里挑HarmonyOS 提供了CollaborationService跨端协同服务能力配合hms.collaboration.service三方库可以在应用里直接嵌入选择其他设备上的文件的系统级入口——选中的文件会被系统传输到当前设备应用只需接收即可。ContinuePublish 发布页正是用了这个能力点击虚线加号弹出的菜单里除了本地设备PhotoViewPicker 选图还会出现由系统动态生成的跨设备菜单项当用户从其他设备选定媒体后数据通过CollaborationServiceStateDialog的回调进入doInsertMedia被解析成图片或视频加入编辑区。本篇将基于项目真实代码把菜单如何生成、数据如何接收讲清楚。说明项目代码里只包含菜单创建与数据接收两部分跨设备传输本身由系统/三方库完成这也是该能力设计的初衷——应用无需自己实现设备发现、连接、传输。本篇不会编造项目之外的 API只基于AddMedia.ets中真实出现的用法展开。知识点讲解canIUse能力查询canIUse(SystemCapability.Collaboration.Service)是 HarmonyOS 提供的能力查询函数参数是能力标识SystemCapability返回该设备当前系统是否支持这项能力。写法形如canIUse(系统能力名)。能力名采用SystemCapability 域名 能力名的层级命名——这里域名是Collaboration协同能力名是Service服务合起来就是跨端协同服务。在写跨设备功能前先做能力查询是官方推荐的能力降级写法——支持就在菜单里加跨设备入口不支持就静默隐藏保证应用在低版本或精简设备上不会报错。同样的canIUse调用还出现在FileUtil.fileCopy里SystemCapability.DistributedDataManager.CommonType说明这套先探测、后使用的模式在工程里是通用约定。跨端协同服务是什么CollaborationService跨端协同服务解决的是这样一个场景用户正在手机上编辑却想引用平板/电脑上的一张图或一段视频。传统做法需要应用自己实现设备发现 → 建连 → 传文件一整套协议成本极高协同服务把这三步全部接管——应用调用createCollaborationServiceMenuItems生成入口系统负责弹出设备列表、引导用户选择远端文件、并通过安全通道把文件传输到本机。应用侧要做的只剩两件事把菜单项挂进自己的 UI以及接收传输完成的回调。这种系统承接重活、应用只做集成的模式是鸿蒙跨端能力设计的核心理念本篇开头那段代码正是它的最小示范。CollaborationService 菜单createCollaborationServiceMenuItemshms.collaboration.service库导出了createCollaborationServiceMenuItems作用是动态创建跨设备选择文件的菜单项。调用时传入过滤器数组Filter指定允许从其他设备选择哪类文件。CollaborationServiceFilter.ALL表示全部类型VIDEO_PICKER表示视频选择器专门用于挑视频。两个过滤器并列传入含义是这些类型的入口都要——与PhotoSelectOptions.MIMEType只能选一类的设计相比协同服务支持一次挂多个入口。数量上限最多可从其他设备拉取多少个文件。传MAX_ADD_MEDIA_NUM9与发布页整体上限保持一致选超了系统会按上限截断或拒绝。函数返回的菜单项直接放进Menu容器即可菜单项的点击、设备列表展示、文件传输都由系统处理——应用这边挂上去就不用管了。CollaborationServiceStateDialog接收跨设备数据与菜单配套的是CollaborationServiceStateDialog组件它提供onState回调onState: (stateCode: number, bufferType: string, buffer: ArrayBuffer) void当跨设备传输完成时回调被触发stateCode状态码非 0 表示失败/取消bufferType数据类型标识如general.image图片、general.video视频buffer数据本体。图片场景下是图片字节流可重建 PixelMap视频场景下是 UTF-8 编码的视频 URI 字符串。也就是说**这个 Dialog 是跨设备数据的着陆点**菜单负责把用户引导到其他设备选文件Dialog 负责把文件送到应用手里。结合本项目源码分析菜单组装MyTestMenu文件路径entry/src/main/ets/view/contentEditor/AddMedia.ets。//远程菜单。 Builder MyTestMenu() { Menu() {//菜单项一从本地设备选图 MenuItem({ symbolStartIcon: new SymbolGlyphModifier($r(sys.symbol.picture_2)), content:$r(app.string.local_device)//Local Devices}) .onClick(() {//未达上限才允许继续添加if(this.mediaUriArray.length CommonConstants.MAX_ADD_MEDIA_NUM) { this.selectImage();//上一篇讲解的本地图库选择 }else{//已达上限弹 Toast 提示 this.getUIContext().getPromptAction().showToast({ message:$r(app.string.add_picture_prompt) }); } })//菜单项二跨设备拉取系统动态生成if(canIUse(SystemCapability.Collaboration.Service)) {//支持跨端协同创建从其他设备选择文件的菜单项 createCollaborationServiceMenuItems([CollaborationServiceFilter.ALL, CollaborationServiceFilter.VIDEO_PICKER], CommonConstants.MAX_ADD_MEDIA_NUM)//数量上限9} } }代码揭示了三层设计条件渲染canIUse(SystemCapability.Collaboration.Service)返回 true 才把跨设备菜单项加进Menu不支持该能力的设备上菜单只有本地设备一项功能完整可用——这是典型的能力降级。系统生成菜单createCollaborationServiceMenuItems的两个参数是过滤器与数量上限。传入[ALL, VIDEO_PICKER]表示图片、视频都可以从其他设备选上限传MAX_ADD_MEDIA_NUM9与整体媒体数量上限保持一致。菜单项的图标、文案、点击行为由系统按 HIG人机交互指南规范生成应用无需操心。菜单挂载位置这个菜单绑定在虚线加号上——addDefaultPic()的.bindMenu(this.MyTestMenu())详见下一篇用户点加号即弹出。数据着陆CollaborationServiceStateDialog doInsertMediaMyTestMenu是出口CollaborationServiceStateDialog是入口。它在AddMedia的 build 里注册build() { Column() { // 跨设备数据接收器媒体传输完成后回调onState CollaborationServiceStateDialog({onState: (stateCode: number, bufferType: string, buffer: ArrayBuffer): void this.doInsertMedia(stateCode, bufferType, buffer) }) this.addMedia(); // 图片视频展示区 } ... }doInsertMedia处理收到的数据是跨设备媒体的分拣中心// Remote images or videos fall into.doInsertMedia(stateCode:number,bufferType:string,buffer: ArrayBuffer): void {// 状态码非 0失败/取消直接忽略if(stateCode !0) { return; }// 数量已达上限也不再接收if(this.mediaUriArray.length CommonConstants.MAX_ADD_MEDIA_NUM) { return; }if(bufferTypegeneral.image) {// 图片从字节流重建 PixelMapletimageSource image.createImageSource(buffer); imageSource.createPixelMap().then((pixelMap) {letuuid util.generateRandomUUID();// 随机名避免重名this.PixelMapToBuffer(pixelMap,uuid);// 编码写入分布式文件this.mediaUriArray.push({ imagePixelMap: pixelMap, mediaName: uuid, mediaType: MediaType.MEDIA_IMAGE }); imageSource.release(); }) }elseif(bufferTypegeneral.video) {// 视频buffer 是 UTF-8 编码的 URI 字符串letuuid util.generateRandomUUID();letdecoder util.TextDecoder.create(utf-8);letvideoUriStr decoder.decodeToString(newUint8Array(buffer));// 把远端视频复制进分布式目录URI 形式writeDistributedFile(this.context,uuid, MediaType.MEDIA_VIDEO,undefined,videoUriStr); this.mediaUriArray.push({ videoUri: videoUriStr, mediaName: uuid, mediaType: MediaType.MEDIA_VIDEO }); } }几个实现细节值得记录双重防护stateCode ! 0挡掉失败与取消mediaUriArray.length 9挡掉超量。两道闸门之后才进入真正的数据处理避免无谓的资源消耗。图片走字节流general.image的 buffer 是图片编码数据用image.createImageSource(buffer)创建图像源、createPixelMap()异步解出 PixelMap 用于 UI 展示再交给上一篇讲过的PixelMapToBuffer落盘写入分布式文件目录为接续做准备。注意imageSource.release()释放资源避免句柄泄漏。视频走 URIgeneral.video的 buffer 其实是一段文本——视频的 URI。代码用util.TextDecoder.create(utf-8)解码成字符串然后调用writeDistributedFile的视频分支把源 URI 指向的文件复制进分布式目录。回想FileUtil.ets中该函数的签名正是(context, uuid, MEDIA_VIDEO, undefined, videoUriStr)——第 4 个参数buf传 undefined、第 5 个参数uri传视频地址内部走fileIo.copyFileSync复制文件}elseif(mediaTypeMediaType.MEDIA_VIDEOuri) { srcFile fileIo.openSync(uri,fileIo.OpenMode.READ_ONLY); fileIo.copyFileSync(srcFile.fd,file.fd);// 把远端视频复制到分布式目录}统一命名图片和视频都用util.generateRandomUUID()生成随机文件名避免与本地图库选出的displayName冲突也让后续接续打包时不依赖用户命名。与本地选图的分工现在可以对比一下发布页两条加媒体通路通路入口数据来源接收方式落盘本地选图菜单Local Devices本机相册PhotoViewPicker 返回 URI缩略图 JPEG跨设备拉取系统生成菜单项其他设备文件CollaborationServiceStateDialog.onState图片字节流 / 视频复制两者殊途同归最终都生成MediaInfo推入mediaUriArray由 AddMedia 的横向 List 统一展示。这种入口多样、出口统一的设计让后续所有处理展示、复制、接续打包只需面对一种数据结构。资源管理细节doInsertMedia里有两处容易被忽略的资源管理letimageSource image.createImageSource(buffer); imageSource.createPixelMap().then((pixelMap) {...imageSource.release();// 用完释放 ImageSource 句柄})ImageSource图像源持有底层解码资源用完必须release()否则长时间跨设备拉取媒体会造成句柄泄漏。类似的释放动作在工程里反复出现uri2pixelMap里imageSourceApi.release()、FileUtil.fileCopy里imageSourceApi.release()以及fileIo打开的文件在finally里closeSync——**凡是打开的系统资源都要配对关闭** 是本工程贯彻最彻底的纪律之一。另外图片与视频都使用util.generateRandomUUID()生成随机名跨设备传过来的文件没有可靠的展示名传输层只给字节流/URI随机 UUID 既避免重名覆盖又避免把不可信的文件名拼进路径引发安全问题。对比本地选图用displayName截取命名两条通路在命名策略上的差异反映了数据可信度的不同——本地数据可信任远端数据一律改名收编。交互流程还原把菜单与接收器串起来一次完整的跨设备拉取体验是点击虚线加号 → bindMenu 弹出 MyTestMenu → canIUse 探测通过 → createCollaborationServiceMenuItems 追加系统菜单项 → 用户点击系统菜单项 → 系统弹出设备列表本机无法直接干预 → 用户在远端设备选择图片/视频 → 系统安全通道传输 → CollaborationServiceStateDialog.onState 回调stateCode0表示成功 → doInsertMedia 按 bufferType 分拣 → mediaUriArray.push → 九宫格刷新注意用户点击菜单项之后应用便失联了——设备选择、文件传输全程在系统侧完成应用只能等onState的最终审判。这也解释了为什么stateCode的校验如此重要它是应用判断整个流程成败的唯一依据非 0 即放弃不猜原因、不重试重试应该由用户重新发起而不是代码自动循环。小结跨设备拉取媒体在本项目中呈现的是一个轻量接入样板应用侧只需要做两件事——挂菜单canIUse做能力探测createCollaborationServiceMenuItems让系统生成从其他设备选文件的菜单项收数据CollaborationServiceStateDialog.onState接收传输结果doInsertMedia按bufferType分拣图片/视频统一转换为MediaInfo进入编辑区。设备发现、连接、文件传输这些重活全部由系统协同服务承担应用复杂度被压到最低。对初级开发者而言记住能力查询canIUse 系统菜单createCollaborationServiceMenuItems 状态回调onState这个三步模式就掌握了跨端能力接入的通用套路。最后把这套模式与本地选图第 16 篇放在一起看能提炼出跨端开发的三个通用心法能力探测先行任何依赖系统/设备能力的代码入口处都要canIUse探测做不到优雅降级的功能迟早会变成崩溃现场系统能办的别自己办设备发现、文件传输、剪贴板读取PasteButton、相册选择PhotoViewPicker——凡有系统级入口优先复用既省代码又安全**异步回调要有终态**stateCode、err这类回调参数是流程的最终裁决宁可多校验一层也不要把失败当成功继续往下走。下一篇回到 UI 本身把 AddMedia 的图片视频展示区拆开看——列表布局、数量上限、复制粘贴菜单、虚线加号一应俱全。本文引用源码entry/src/main/ets/view/contentEditor/AddMedia.ets、entry/src/main/ets/utils/FileUtil.ets、entry/src/main/ets/constants/CommonConstants.ets

相关新闻

高校科研团队需要哪些材料完成技术成果电子汇编?

高校科研团队需要哪些材料完成技术成果电子汇编?

2026/8/25 22:35:41

观点作者:科易网-国家科技成果转化(厦门)示范基地 近年来,随着我国科技创新能力的持续提升,高校科研团队在科研成果产出方面取得了显著进展。然而,伴随着成果数量的激增,如何高效地将科研成果进…

低腰蓝色牛仔与成年百褶裙:九组高清时尚提示词

低腰蓝色牛仔与成年百褶裙:九组高清时尚提示词

2026/8/25 22:35:41

同一组蓝色下装,用九种人物、空间和光线写出九种成片气质。 摘要| 这组可复用的高清摄影提示词为 19—22 岁虚构亚洲成年女性设计,包含 5 套蓝色低腰修身全长牛仔裤与 4 套成年学院风膝上百褶裙。九张图分别落在陶艺、天文、黑胶、灯光、花市…

ruflo:用 TypeScript 元 harness 编排多 Agent Swarm 构建自主工作流与对话系统

ruflo:用 TypeScript 元 harness 编排多 Agent Swarm 构建自主工作流与对话系统

2026/8/25 22:35:41

1. 引言 ruvnet/ruflo 是一个用 TypeScript 实现的元 harness(meta-harness),目标是解决一个越来越普遍的问题:当单个编码 Agent(如 Codex、Claude Code)能力有限时,如何把多个 Agent 组织成一支…

Java单例模式深度解析与面试实战指南

Java单例模式深度解析与面试实战指南

2026/8/25 23:25:43

1. 单例模式的核心概念与面试权重单例模式(Singleton Pattern)作为创建型设计模式的代表,在Java面试中的出现频率高达78%(根据2023年主流大厂面试题库统计)。其核心在于确保一个类仅有一个实例,并提供一个全…

政治学硕士论文降AI教程:政治专业研究生论文AIGC超标4.8元知网一次达标完整操作指南

政治学硕士论文降AI教程:政治专业研究生论文AIGC超标4.8元知网一次达标完整操作指南

2026/8/25 23:25:43

政治学硕士论文降AI教程:政治专业研究生论文AIGC超标4.8元知网一次达标完整操作指南 处理政治学硕士论文降AI时最怕两件事:降不下来,和改完不知道对不对。 这篇把整个流程梳理清楚,用嘎嘎降AI(www.aigcleaner.com&am…

视频号算法分发逻辑下,新手账号冷启动与养号策略研究

视频号算法分发逻辑下,新手账号冷启动与养号策略研究

2026/8/25 23:25:43

不少视频号新手发布作品后,常会出现播放量低迷的问题,因此大多会在网上查找养号方法。网络上的养号教程繁杂且操作繁琐,各类要求各不相同。实际上视频号养号并不复杂,核心只是让平台识别并摸清账号的创作内容定位。一、养号核心原…

数据结构与算法面试核心考点解析

数据结构与算法面试核心考点解析

2026/8/25 23:25:43

1. 数据结构与算法面试核心考点解析在技术岗位的招聘过程中,数据结构与算法能力始终是衡量候选人编程基本功和逻辑思维能力的黄金标准。根据我对上百场技术面试的观察统计,约83%的淘汰发生在算法题环节,而其中近半数的失败源于对基础数据结构…

高新技术产品认证:企业创新发展的权威赋能

高新技术产品认证:企业创新发展的权威赋能

2026/8/25 23:25:43

高新技术产品认证是各地科技主管部门依据国家科创政策开展的官方资质认定,依托《高新技术企业认定管理办法》等权威文件实施,聚焦产品核心技术创新性、知识产权合规性与市场先进性,是评判企业产品科技含量、创新实力与市场竞争力的核心标准&a…

国产AI数据大屏生成工具对比分析与数字孪生大屏选型指南

国产AI数据大屏生成工具对比分析与数字孪生大屏选型指南

2026/8/25 23:15:43

我们公司最近在筹备一个智慧园区的数字孪生展厅,需要一块能展示园区实时运营数据的大屏。本来打算找外包公司做,但报价动辄几十万,而且后续数据更新还得依赖他们,想想就不划算。于是我开始研究市面上国产的AI数据大屏生成工具&…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/24 19:53:32

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/24 19:56:07

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/24 21:16:09

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

2026/8/25 0:04:34

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory Meta Description:GetQzonehistory 是一个QQ空间历史说…

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

2026/8/25 0:04:35

【题目来源】 https://www.luogu.com.cn/problem/P7912 【题目描述】 小熊的水果店里摆放着一排 n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1,2,…,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里&#x…

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

2026/8/25 0:04:35

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG 【免费下载链接】transformers.js State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server! 项目地址: https:/…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/22 4:13:47

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/22 1:32:34

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…