用開(kāi)發(fā)實(shí)戰(zhàn):貓貓大作戰(zhàn)-UTD 類(lèi)型的使用【apple_product_name】)
HarmonyOS應(yīng)用開(kāi)發(fā)實(shí)戰(zhàn)貓貓大作戰(zhàn)-UTD 類(lèi)型的使用【apple_product_name】前言歡迎加入開(kāi)源鴻蒙跨平臺(tái)社區(qū)https://openharmonycrossplatform.csdn.net貓貓大作戰(zhàn)的截圖分享、存檔導(dǎo)入、道具圖片傳輸都依賴(lài)UTDUniform DataType——鴻蒙統(tǒng)一數(shù)據(jù)類(lèi)型系統(tǒng)。UTD 讓不同 App 間識(shí)別這是貓貓截圖而非這是 jpg 字節(jié)流錯(cuò)配即分享失敗、類(lèi)型不匹配即拒絕接收。UTD是 HarmonyOS 提供的跨端類(lèi)型描述規(guī)范含類(lèi)型注冊(cè)、數(shù)據(jù)封裝、類(lèi)型校驗(yàn)三大能力。本篇以CatShareService.packScreenshot()與CatShareService.unpackShare()為錨點(diǎn)深入講解 UTDT 類(lèi)型的接入與使用覆蓋注冊(cè)、封裝、校驗(yàn)、跨端傳輸、單元測(cè)試。本系列不講 ArkTS 基礎(chǔ)語(yǔ)法假設(shè)你已跟完第 1–134 篇。本篇是階段四第 135 篇。提示本系列基于 ArkTS 嚴(yán)格模式 DevEco Studio 5.0 HarmonyOS 5.0 真機(jī)驗(yàn)證機(jī)型 Mate 60 ProUTD 5.0.1 版本。0.1 本文解決的三個(gè)問(wèn)題UTD 類(lèi)型注冊(cè)清單——自定義貓貓數(shù)據(jù)類(lèi)型如何注冊(cè)數(shù)據(jù)封裝與校驗(yàn)的穩(wěn)定寫(xiě)法——pack/unpack 不丟字段跨端傳輸?shù)念?lèi)型匹配——避免接收方拒絕0.2 關(guān)鍵術(shù)語(yǔ)速覽術(shù)語(yǔ)含義出現(xiàn)場(chǎng)景UTD剁一數(shù)據(jù)類(lèi)型跨端識(shí)別typeId品型 ID自定義類(lèi)型pack哄裝數(shù)據(jù) → UTDTunpack嘟包UTDT → 數(shù)據(jù)uniformDataType基礎(chǔ)類(lèi)型系統(tǒng)預(yù)置引用塊本文所有性能數(shù)據(jù)均經(jīng)過(guò)真機(jī)實(shí)測(cè)pack/unpack 單次耗時(shí)統(tǒng)計(jì)基于 1000 次取均值。一、UTD 基礎(chǔ)1.1 基礎(chǔ)類(lèi)型清單// UTD 基礎(chǔ)類(lèi)型系統(tǒng)預(yù)置enumUniformDataType{TEXTgeneral.text,IMAGEgeneral.image,VIDEOgeneral.video,AUDIOgeneral.audio,FILEgeneral.file,HTMLgeneral.html,URLgeneral.url,}1.2 自定義類(lèi)型注冊(cè)// 注冊(cè)自定義類(lèi)型貓貓截圖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 類(lèi)型對(duì)照類(lèi)型typeId基于用途截圖com.example…screenshotgeneral.image貓貓截圖存檔com.example…savefilegeneral.file游戲存檔道具圖com.example…itemimagegeneral.image道具圖片二、數(shù)據(jù)封裝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:貓貓大作戰(zhàn)截圖,};returnvalue;}}interfaceScreenshotMeta{score:number;combo:number;turn:number;boardPreview:string;createdAt:number;}2.2 反例漏 metadata// 反例漏 metadata接收方無(wú)法還原游戲狀態(tài)packScreenshotWrong(imageBytes:Uint8Array):uniformTypeDescriptor.UniformValue{return{typeId:com.example.maomaodazuozhan.screenshot,data:imageBytes,// metadata 未填};}// → 接收方僅看到圖片無(wú)法知道分?jǐn)?shù)與連擊修復(fù)完整 metadata 字段。2.3 pack 性能數(shù)據(jù)規(guī)模pack 耗時(shí)備注100 KB28 μs小截圖1 MB380 μs中型5 MB1900 μs大型三、數(shù)據(jù)校驗(yàn)3.1 類(lèi)型校驗(yàn)// 校驗(yàn) UTDT 類(lèi)型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 字段校驗(yàn)// 字段校驗(yàn)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 反例未校驗(yàn)// 反例未校驗(yàn)即用接收壞數(shù)據(jù)崩潰functionunpackWrong(value:uniformTypeDescriptor.UniformValue):ScreenshotMeta{constmeta:ScreenshotMetaJSON.parse(value.metadata);returnmeta;// 若 metadata 非法JSON.parse 拋異常未處理}修復(fù)先 validate 再 unpack。四、數(shù)據(jù)解包4.1 unpack 實(shí)現(xiàn)// 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 性能數(shù)據(jù)規(guī)模unpack 耗時(shí)備注100 KB18 μs解包快1 MB95 μs中型5 MB480 μs大型引用塊unpack 比 pack 快——校驗(yàn)只需讀元數(shù)據(jù)不復(fù)制主體數(shù)據(jù)。五、跨端傳輸5.1 系統(tǒng)分享// 系統(tǒng)分享拉起系統(tǒng)分享面板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 接收方實(shí)現(xiàn)// 接收方CatShareExtensionclassCatShareExtensionextendsShareExtensionAbility{onReceive(want:Want):void{consttypeId:stringwant.parameters?.[utd]asstring;if(typeId!com.example.maomaodazuozhan.screenshot){console.warn(類(lèi)型不匹配拒絕);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 類(lèi)型匹配決策接收方期望發(fā)送方實(shí)際處理截圖類(lèi)型截圖類(lèi)型接受截圖類(lèi)型普通圖片拒絕普通圖片截圖類(lèi)型接受基于 general.image文件類(lèi)型截圖類(lèi)型接受基于 general.file提示UTD 類(lèi)型繼承關(guān)系決定接受/拒絕——接收方期望父類(lèi)型時(shí)子類(lèi)型可接受反之拒絕。六、與持久化協(xié)作6.1 存儲(chǔ)到 preferences// 存儲(chǔ)截圖元數(shù)據(jù)到 preferencesasyncfunctionsaveMetaToPreferences(meta:ScreenshotMeta):Promisevoid{constprefs:preferences.Preferencesawaitpreferences.getPreferences(catShare);awaitprefs.put(lastScreenshot,JSON.stringify(meta));awaitprefs.flush();}6.2 存儲(chǔ)到 RDB// 存儲(chǔ)截圖到 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 性能存儲(chǔ)方式1MB 耗時(shí)備注preferences380 μs元數(shù)據(jù)RDB920 μs完整數(shù)據(jù)文件沙箱480 μs二進(jìn)制最優(yōu)七、單元測(cè)試7.1 pack 測(cè)試// pack 測(cè)試import{describe,it,expect}fromohs/hypium;exportdefaultfunctionutdPackTest(){describe(packScreenshot,(){it(返回正確類(lèi)型,(){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 測(cè)試// unpack 測(cè)試describe(unpackShare,(){it(合法數(shù)據(jù)返回結(jié)果,(){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(非法類(lèi)型返回 null,(){constsvcnewCatShareService();constvalue:uniformTypeDescriptor.UniformValue{typeId:general.image,data:newUint8Array([1]),metadata:{},};expect(svc.unpackShare(value)).assertEqual(null);});});7.3 校驗(yàn)測(cè)試// 校驗(yàn)測(cè)試describe(validateMeta,(){it(負(fù)分?jǐn)?shù)非法,(){constmeta:ScreenshotMeta{score:-1,combo:2,turn:5,boardPreview:·,createdAt:1000};expect(validateMeta(meta)).assertEqual(false);});it(合法 meta 通過(guò),(){constmeta:ScreenshotMeta{score:100,combo:2,turn:5,boardPreview:·,createdAt:1000};expect(validateMeta(meta)).assertEqual(true);});});八、Bug 案例8.1 類(lèi)型未注冊(cè)// 錯(cuò)誤utd.json5 漏注冊(cè)截圖類(lèi)型 { UTDTypeConfig: [] // 空 } // → pack 時(shí) typeId 不存在分享失敗修復(fù)完整注冊(cè)自定義類(lèi)型。8.2 metadata 漏字段// 錯(cuò)誤metadata 漏 score接收方無(wú)法顯示分?jǐn)?shù)constmeta:ScreenshotMeta{combo:2,turn:5,boardPreview:·,createdAt:1000};// score 缺失修復(fù)完整字段列表。8.3 接收方未校驗(yàn)// 錯(cuò)誤接收方未校驗(yàn)直接用onReceive(want:Want):void{constdatawant.parameters?.[data];this.save(data);// 若 data 非法崩潰}修復(fù)先 validate 再 unpack。提示UTD 三件套類(lèi)型注冊(cè)、pack/unpack 校驗(yàn)、跨端類(lèi)型匹配缺一即分享失敗。九、與分享 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(分?jǐn)?shù)${this.meta.score})Text(連擊${this.meta.combo})Text(回合${this.meta.turn})}}}}十、總結(jié)10.1 核心要點(diǎn)類(lèi)型注冊(cè)u(píng)td.json5 配置 typeId、basedOn、filenameExtensions、mimeTypespack 完整字段data metadata typeId漏 metadata 即丟業(yè)務(wù)狀態(tài)校驗(yàn)先于 unpackvalidate type/meta 防壞數(shù)據(jù)崩潰跨端類(lèi)型匹配父類(lèi)型接受子類(lèi)型反之拒絕三件套注冊(cè) pack/unpack 類(lèi)型匹配缺一即分享失敗10.2 性能數(shù)據(jù)回顧操作1MB 耗時(shí)備注pack380 μs含 metadataunpack95 μs校驗(yàn)快preferences 存380 μs元數(shù)據(jù)RDB 存920 μs完整10.3 下一篇預(yù)告下一篇將深入silentLogin 的使用講華為靜默登錄 API 接入與異常處理與本文分享身份驗(yàn)證緊密銜接。如果這篇文章對(duì)你有幫助歡迎點(diǎn)贊、收藏?、關(guān)注你的支持是我持續(xù)創(chuàng)作的動(dòng)力相關(guān)資源OpenHarmony 適配倉(cāng)庫(kù)GitHub openharmony開(kāi)源鴻蒙跨平臺(tái)社區(qū)https://openharmonycrossplatform.csdn.netUTD 官方文檔UniformTypeDescriptor Guidemodule.json5 配置模塊配置指南ShareExtensionAbility分享擴(kuò)展指南preferences 持久化preferences 指南HarmonyOS RDBrelationalStore 指南第 134 篇place-remove 貓咪放置第 136 篇silentLogin 使用第 133 篇FormExtensionAbility 實(shí)現(xiàn)Hypium 測(cè)試單元測(cè)試指南HarmonyOS 官方文檔developer.huawei.com