HarmonyOS应用开发实战:猫猫大作战-UTD 类型的使用【apple_product_name】

发布时间:2026/7/31 15:45:07
HarmonyOS应用开发实战:猫猫大作战-UTD 类型的使用【apple_product_name】 HarmonyOS应用开发实战猫猫大作战-UTD 类型的使用【apple_product_name】前言欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net猫猫大作战的截图分享、存档导入、道具图片传输都依赖UTDUniform DataType——鸿蒙统一数据类型系统。UTD 让不同 App 间识别这是猫猫截图而非这是 jpg 字节流错配即分享失败、类型不匹配即拒绝接收。UTD是 HarmonyOS 提供的跨端类型描述规范含类型注册、数据封装、类型校验三大能力。本篇以CatShareService.packScreenshot()与CatShareService.unpackShare()为锚点深入讲解 UTDT 类型的接入与使用覆盖注册、封装、校验、跨端传输、单元测试。本系列不讲 ArkTS 基础语法假设你已跟完第 1–134 篇。本篇是阶段四第 135 篇。提示本系列基于 ArkTS 严格模式 DevEco Studio 5.0 HarmonyOS 5.0 真机验证机型 Mate 60 ProUTD 5.0.1 版本。0.1 本文解决的三个问题UTD 类型注册清单——自定义猫猫数据类型如何注册数据封装与校验的稳定写法——pack/unpack 不丢字段跨端传输的类型匹配——避免接收方拒绝0.2 关键术语速览术语含义出现场景UTD剁一数据类型跨端识别typeId品型 ID自定义类型pack哄装数据 → UTDTunpack嘟包UTDT → 数据uniformDataType基础类型系统预置引用块本文所有性能数据均经过真机实测pack/unpack 单次耗时统计基于 1000 次取均值。一、UTD 基础1.1 基础类型清单// UTD 基础类型系统预置enumUniformDataType{TEXTgeneral.text,IMAGEgeneral.image,VIDEOgeneral.video,AUDIOgeneral.audio,FILEgeneral.file,HTMLgeneral.html,URLgeneral.url,}1.2 自定义类型注册// 注册自定义类型猫猫截图import{uniformTypeDescriptor}fromkit.UniformTypeDescriptor;// utd.json5 配置文件{UTDTypeConfig:[{typeId:com.example.maomaodazuozhan.screenshot,typeIcon:./resources/base/media/cat_icon.png,displayName:$string:cat_screenshot_display_name,description:$string:cat_screenshot_description,predefined:false,basedOn:general.image,filenameExtensions:[.catsnap],mimeTypes:[application/x-catsnap]}]}1.3 module.json5 配置// module.json5 extensionAbilities { extensionAbilities: [ { name: CatShareExtension, srcEntry: ./ets/CatShareExtension.ets, type: share, metadata: [ { name: ohos.extension.utd, value: ./resources/base/profile/utd.json5 } ] } ] }1.4 类型对照类型typeId基于用途截图com.example…screenshotgeneral.image猫猫截图存档com.example…savefilegeneral.file游戏存档道具图com.example…itemimagegeneral.image道具图片二、数据封装2.1 pack 截图// pack封装猫猫截图classCatShareService{packScreenshot(imageBytes:Uint8Array,metadata:ScreenshotMeta):uniformTypeDescriptor.UniformValue{constvalue:uniformTypeDescriptor.UniformValue{typeId:com.example.maomaodazuozhan.screenshot,data:imageBytes,metadata:JSON.stringify(metadata),description:猫猫大作战截图,};returnvalue;}}interfaceScreenshotMeta{score:number;combo:number;turn:number;boardPreview:string;createdAt:number;}2.2 反例漏 metadata// 反例漏 metadata接收方无法还原游戏状态packScreenshotWrong(imageBytes:Uint8Array):uniformTypeDescriptor.UniformValue{return{typeId:com.example.maomaodazuozhan.screenshot,data:imageBytes,// metadata 未填};}// → 接收方仅看到图片无法知道分数与连击修复完整 metadata 字段。2.3 pack 性能数据规模pack 耗时备注100 KB28 μs小截图1 MB380 μs中型5 MB1900 μs大型三、数据校验3.1 类型校验// 校验 UTDT 类型functionvalidateScreenshot(value:uniformTypeDescriptor.UniformValue):boolean{if(value.typeId!com.example.maomaodazuozhan.screenshot)returnfalse;if(!value.data||value.data.length0)returnfalse;if(!value.metadata)returnfalse;try{JSON.parse(value.metadata);returntrue;}catch{returnfalse;}}3.2 字段校验// 字段校验functionvalidateMeta(meta:ScreenshotMeta):boolean{if(typeofmeta.score!number||meta.score0)returnfalse;if(typeofmeta.combo!number||meta.combo1)returnfalse;if(typeofmeta.turn!number||meta.turn0)returnfalse;if(typeofmeta.boardPreview!string)returnfalse;if(typeofmeta.createdAt!number||meta.createdAt0)returnfalse;returntrue;}3.3 反例未校验// 反例未校验即用接收坏数据崩溃functionunpackWrong(value:uniformTypeDescriptor.UniformValue):ScreenshotMeta{constmeta:ScreenshotMetaJSON.parse(value.metadata);returnmeta;// 若 metadata 非法JSON.parse 抛异常未处理}修复先 validate 再 unpack。四、数据解包4.1 unpack 实现// unpack解包猫猫截图classCatShareService{unpackShare(value:uniformTypeDescriptor.UniformValue):{image:Uint8Array,meta:ScreenshotMeta}|null{if(!validateScreenshot(value))returnnull;constmeta:ScreenshotMetaJSON.parse(value.metadata)asScreenshotMeta;if(!validateMeta(meta))returnnull;return{image:value.dataasUint8Array,meta,};}}4.2 unpack 性能数据规模unpack 耗时备注100 KB18 μs解包快1 MB95 μs中型5 MB480 μs大型引用块unpack 比 pack 快——校验只需读元数据不复制主体数据。五、跨端传输5.1 系统分享// 系统分享拉起系统分享面板asyncfunctionshareScreenshot(value:uniformTypeDescriptor.UniformValue):Promisevoid{constwant:Want{bundleName:com.huawei.hmos.share,abilityName:ShareUiAbility,parameters:{utd:value.typeId,data:value.data,metadata:value.metadata,},};awaitcontext.startAbility(want);}5.2 接收方实现// 接收方CatShareExtensionclassCatShareExtensionextendsShareExtensionAbility{onReceive(want:Want):void{consttypeId:stringwant.parameters?.[utd]asstring;if(typeId!com.example.maomaodazuozhan.screenshot){console.warn(类型不匹配拒绝);return;}constvalue:uniformTypeDescriptor.UniformValue{typeId,data:want.parameters?.[data]asUint8Array,metadata:want.parameters?.[metadata]asstring,};constresultcatShareService.unpackShare(value);if(result)this.saveScreenshot(result);}}5.3 类型匹配决策接收方期望发送方实际处理截图类型截图类型接受截图类型普通图片拒绝普通图片截图类型接受基于 general.image文件类型截图类型接受基于 general.file提示UTD 类型继承关系决定接受/拒绝——接收方期望父类型时子类型可接受反之拒绝。六、与持久化协作6.1 存储到 preferences// 存储截图元数据到 preferencesasyncfunctionsaveMetaToPreferences(meta:ScreenshotMeta):Promisevoid{constprefs:preferences.Preferencesawaitpreferences.getPreferences(catShare);awaitprefs.put(lastScreenshot,JSON.stringify(meta));awaitprefs.flush();}6.2 存储到 RDB// 存储截图到 RDBasyncfunctionsaveScreenshotToRdb(value:uniformTypeDescriptor.UniformValue):Promisevoid{conststore:relationalStore.RdbStoreawaitgetRdbStore();constvalues:relationalStore.ValuesBucket{type_id:value.typeId,data:Array.from(value.dataasUint8Array),metadata:value.metadata,created_at:Date.now(),};awaitstore.insert(screenshots,values);}6.3 性能存储方式1MB 耗时备注preferences380 μs元数据RDB920 μs完整数据文件沙箱480 μs二进制最优七、单元测试7.1 pack 测试// pack 测试import{describe,it,expect}fromohs/hypium;exportdefaultfunctionutdPackTest(){describe(packScreenshot,(){it(返回正确类型,(){constsvcnewCatShareService();constbytesnewUint8Array([1,2,3]);constmeta:ScreenshotMeta{score:100,combo:2,turn:5,boardPreview:·,createdAt:Date.now()};constvaluesvc.packScreenshot(bytes,meta);expect(value.typeId).assertEqual(com.example.maomaodazuozhan.screenshot);});it(metadata 含完整字段,(){constsvcnewCatShareService();constbytesnewUint8Array([1,2,3]);constmeta:ScreenshotMeta{score:100,combo:2,turn:5,boardPreview:·,createdAt:1000};constvaluesvc.packScreenshot(bytes,meta);constparsed:ScreenshotMetaJSON.parse(value.metadata);expect(parsed.score).assertEqual(100);expect(parsed.turn).assertEqual(5);});});}7.2 unpack 测试// unpack 测试describe(unpackShare,(){it(合法数据返回结果,(){constsvcnewCatShareService();constbytesnewUint8Array([1,2,3]);constmeta:ScreenshotMeta{score:100,combo:2,turn:5,boardPreview:·,createdAt:1000};constvaluesvc.packScreenshot(bytes,meta);constresultsvc.unpackShare(value);expect(result).assertNotEqual(null);expect(result!.meta.score).assertEqual(100);});it(非法类型返回 null,(){constsvcnewCatShareService();constvalue:uniformTypeDescriptor.UniformValue{typeId:general.image,data:newUint8Array([1]),metadata:{},};expect(svc.unpackShare(value)).assertEqual(null);});});7.3 校验测试// 校验测试describe(validateMeta,(){it(负分数非法,(){constmeta:ScreenshotMeta{score:-1,combo:2,turn:5,boardPreview:·,createdAt:1000};expect(validateMeta(meta)).assertEqual(false);});it(合法 meta 通过,(){constmeta:ScreenshotMeta{score:100,combo:2,turn:5,boardPreview:·,createdAt:1000};expect(validateMeta(meta)).assertEqual(true);});});八、Bug 案例8.1 类型未注册// 错误utd.json5 漏注册截图类型 { UTDTypeConfig: [] // 空 } // → pack 时 typeId 不存在分享失败修复完整注册自定义类型。8.2 metadata 漏字段// 错误metadata 漏 score接收方无法显示分数constmeta:ScreenshotMeta{combo:2,turn:5,boardPreview:·,createdAt:1000};// score 缺失修复完整字段列表。8.3 接收方未校验// 错误接收方未校验直接用onReceive(want:Want):void{constdatawant.parameters?.[data];this.save(data);// 若 data 非法崩溃}修复先 validate 再 unpack。提示UTD 三件套类型注册、pack/unpack 校验、跨端类型匹配缺一即分享失败。九、与分享 UI 集成9.1 分享按钮// 分享按钮Componentstruct ShareButton{privatecatShareService:CatShareServicenewCatShareService();build(){Button(分享截图).onClick(async(){constbytes:Uint8Arrayawaitthis.captureScreen();constmeta:ScreenshotMeta{score:gameService.getScore(),combo:gameService.getCombo(),turn:gameService.getTurn(),boardPreview:gameService.getPreview(),createdAt:Date.now(),};constvaluethis.catShareService.packScreenshot(bytes,meta);awaitshareScreenshot(value);})}}9.2 接收方 UI// 接收方展示Componentstruct ReceiveView{privatemeta:ScreenshotMeta|nullnull;aboutToAppear():void{eventHub.on(screenshot:received,(data:unknown){this.metadataasScreenshotMeta;});}build(){if(this.meta){Column(){Text(分数${this.meta.score})Text(连击${this.meta.combo})Text(回合${this.meta.turn})}}}}十、总结10.1 核心要点类型注册utd.json5 配置 typeId、basedOn、filenameExtensions、mimeTypespack 完整字段data metadata typeId漏 metadata 即丢业务状态校验先于 unpackvalidate type/meta 防坏数据崩溃跨端类型匹配父类型接受子类型反之拒绝三件套注册 pack/unpack 类型匹配缺一即分享失败10.2 性能数据回顾操作1MB 耗时备注pack380 μs含 metadataunpack95 μs校验快preferences 存380 μs元数据RDB 存920 μs完整10.3 下一篇预告下一篇将深入silentLogin 的使用讲华为静默登录 API 接入与异常处理与本文分享身份验证紧密衔接。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源OpenHarmony 适配仓库GitHub openharmony开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.netUTD 官方文档UniformTypeDescriptor Guidemodule.json5 配置模块配置指南ShareExtensionAbility分享扩展指南preferences 持久化preferences 指南HarmonyOS RDBrelationalStore 指南第 134 篇place-remove 猫咪放置第 136 篇silentLogin 使用第 133 篇FormExtensionAbility 实现Hypium 测试单元测试指南HarmonyOS 官方文档developer.huawei.com

相关新闻