【開發(fā)者說】欄目是為HarmonyOS開發(fā)者提供的展示和分享平臺,在這里,大家可以發(fā)表自己的技術(shù)洞察和見解,也可以展示自己的開發(fā)心得和成果。
歡迎大家積極投稿,后臺回復(fù)【投稿】,即可獲得投稿渠道。期待你們的分享~
01
什么是分布式數(shù)據(jù)對象
在可信組網(wǎng)環(huán)境下,多個相互組網(wǎng)認證的設(shè)備將各自創(chuàng)建的對象加入同一個sessionId,使得加入的多個數(shù)據(jù)對象之間可以同步數(shù)據(jù),也就是說,當某一數(shù)據(jù)對象屬性發(fā)生變更時,其他數(shù)據(jù)對象會檢測到這一變更,同時將自身屬性更新。此時,該sessionId下的所有數(shù)據(jù)對象屬性相同,這樣的數(shù)據(jù)對象稱之為分布式數(shù)據(jù)對象。此外,分布式數(shù)據(jù)對象可以被動退出sessionId,當分布式數(shù)據(jù)對象退出sessionId后,該對象將檢測不到其他對象的變更。
02分布式數(shù)據(jù)對象能力
1、分布式數(shù)據(jù)對象創(chuàng)建2、分布式數(shù)據(jù)對象查詢3、分布式數(shù)據(jù)對象修改4、分布式數(shù)據(jù)對象刪除5、分布式數(shù)據(jù)對象保存6、分布式數(shù)據(jù)對象訂閱(數(shù)據(jù)變更,上下線)7、分布式數(shù)據(jù)對象加入、退出分布式組網(wǎng)
03前提準備
1、開發(fā)工具:DevEco Studio 3.1.0.5012、API:9
3、SDK版本:3.2.12.504創(chuàng)建一個新的項目
新建項目,選擇API9版本,stage模型。
05權(quán)限申請
1、使用到的權(quán)限- ohos.permission.DISTRIBUTED_DATASYNC
- 允許不同設(shè)備間的數(shù)據(jù)交換
- 權(quán)限級別:normal
- 授權(quán)方式:user_grant
- ACL使能:TRUE
2、配置文件申明
首先,在項目的模塊級目錄下找到并打開module.json5文件,如下圖:
在module下的對象里添加如下申明:
此時,配置文件中的權(quán)限申明就完成了,但是,此時我們還不能獲得這些權(quán)限。由于ohos.permission.DISTRIBUTED_DATASYNC權(quán)限是ACL使能為TRUE的權(quán)限,需要在簽名工具文件中說明一下。
如何找到對應(yīng)的簽名工具文件呢?我們在安裝DevEcoStudio的時候是下載好了OpenHarmony的SDK的,此時在OpenHarmony文件夾中,打開 “SdkOpenHarmony SDK版本 oolchainslib” 該路徑,此時在lib文件夾中,咱們可以找到兩個json文件,分別為UnsgnedDebugProfileTemplate.json和UnsgnedReleasedProfileTemplate.json,點擊并打開這兩個文件,添加如下權(quán)限:
3、權(quán)限申請編碼
在申請ohos.permission.DISTRIBUTED_DATASYNC權(quán)限時,其文檔中將其標注為用戶手動授權(quán)的權(quán)限,此時需要我們動態(tài)申請權(quán)限,在項目中,我們新建一個ets文件,我這里取名為RequestPermission.ets。
首先,導(dǎo)入以下包:
import abilityAccessCtrl, { Permissions } from '@ohos.abilityAccessCtrl';
import bundleManager from '@ohos.bundle.bundleManager';
importcommonfrom'@ohos.app.ability.common';
(左右滑動查看更多)
獲取訪問控制模塊對象實例:
let atManager = abilityAccessCtrl.createAtManager();
(左右滑動查看更多)
編寫如下方法(這里使用的是異步函數(shù)):
export async function checkAccessTokenID(permission: Array) {
// 獲取應(yīng)用程序的accessTokenID
let tokenId: number;
let grantStatus: Array = []
try {
let bundleInfo: bundleManager.BundleInfo = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;
tokenId = appInfo.accessTokenId;
} catch (err) {
console.error(`getBundleInfoForSelf failed, code is ${err.code}, message is ${err.message}`);
}
// 校驗應(yīng)用是否被授予權(quán)限,若申請多個權(quán)限,建議循環(huán)檢查多個權(quán)限
for (let index = 0;index < permission.length; index++) {
try {
grantStatus.push(await atManager.checkAccessToken(tokenId, permission[index]))
} catch (err) {
console.error(`checkAccessToken failed, code is ${err.code}, message is ${err.message}`);
}
}
return grantStatus;
}
export async function checkPermission(context: common.UIAbilityContext, permissions: Array) {
let grantStatus: Array = await checkAccessTokenID(permissions)
for (let i = 0; i < grantStatus.length; i++) {
if (grantStatus[i] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
console.info(`${permissions[i].toString()} 已授權(quán)`)
} else {
//申請權(quán)限
console.info('開始向用戶申請權(quán)限')
requestPermissionFromUser(context, permissions)
}
}
}
export async function requestPermissionFromUser(context: common.UIAbilityContext, permissions: Array) {
// requestPermissionsFromUser會判斷權(quán)限的授權(quán)狀態(tài)來決定是否喚起彈窗
atManager.requestPermissionsFromUser(context, permissions).then((data) => {
let grantStatus: Array<number> = data.authResults
let length: number = grantStatus.length
for (let i = 0;i < length; i++) {
if (grantStatus[i] === 0) {
// 用戶授權(quán),可以繼續(xù)訪問目標操作
console.info(`${permissions[i].toString()} 權(quán)限申請成功`)
} else {
// 用戶拒絕授權(quán),提示用戶必須授權(quán)才能訪問當前頁面的功能,并引導(dǎo)用戶到系統(tǒng)設(shè)置中打開相應(yīng)的權(quán)限
console.info(`${permissions[i].toString()} 權(quán)限申請被用戶拒絕`)
}
}
// 授權(quán)成功
})
}
(左右滑動查看更多)
此時,我們申請權(quán)限的方法就算編寫完成了,在應(yīng)用入口,即EntryAbility.ts文件中的
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam)
方法中回調(diào)權(quán)限申請函數(shù):
requestPermissionFromUser(this.context,PERMISSIONS)
其中,PERMISSIONS定義如下:
const
PERMISSIONS:Array=['ohos.permission.DISTRIBUTED_DATASYNC']
到此,我們的權(quán)限申請就算完完全全完成啦,當用戶第一次安裝并打開應(yīng)用的時候,應(yīng)用會向用戶通過彈窗形式申請權(quán)限,用戶點擊授權(quán)即可賦予應(yīng)用相應(yīng)的權(quán)限啦~06上手分布式數(shù)據(jù)對象代碼開發(fā)
登錄了同一華為帳號的HarmonyOS設(shè)備已經(jīng)默認了進行了組網(wǎng)認證,所以在進行分布式數(shù)據(jù)對象開發(fā)之前無需再進行多設(shè)備組網(wǎng)認證這一階段的開發(fā),開發(fā)變得相對簡單了起來。首先,咱們制作一個簡易UI界面(UI界面僅供參考),如下圖所示:
相信對于有HarmonyOS開發(fā)經(jīng)驗的小伙伴們來說這樣的UI界面制作并不困難,其中紅色圓點、綠色圓點為設(shè)備狀態(tài),當設(shè)備狀態(tài)發(fā)生改變?nèi)缦戮€時,顏色變?yōu)榧t色,UI界面代碼如下:
import router from '@ohos.router'
import { DistributedDeviceManageFunc } from '../modules/DistributedDeviceManager/DistributedDeviceManagerFunctions'
import DistributedObjectFunc from '../modules/DistributedObject/DistributedObjectFunctions'
import { ContinuationDeviceManagerDialog } from '../view/ContinuationDeviceManagerDialog'
import { DistributedDeviceManagerDialog } from '../view/DistributedDeviceManagerDialog'
AppStorage.SetOrCreate('distributedDeviceList', [])
AppStorage.SetOrCreate('message', '分布式數(shù)據(jù)對象Demo測試')
AppStorage.SetOrCreate('statusColor', '#ff4fc100')
AppStorage.SetOrCreate('distributedColor', '#ffff0000')
struct DistributedObjectDemo {
'message') message: string = ''
( 'statusColor') statusColor: string = ''
( 'distributedColor') distributedColor: string = ''
( 'distributedObj') distributedObj: DistributedObjectFunc = new DistributedObjectFunc()
(
navigationTitle() {
Row({ space: '10vp' }) {
Button({ type: ButtonType.Normal }) {
Image($rawfile('ic_public_back.svg'))
.size({
width: '24vp',
height: '24vp'
})
}
.width('36vp')
.height('36vp')
.backgroundColor(Color.White)
.borderRadius('10vp')
.onClick(() => {
DistributedDeviceManageFunc.release()
router.back()
})
Text('分布式數(shù)據(jù)對象測試')
.fontWeight(FontWeight.Bold)
.fontSize('20vp')
Blank()
Button({ type: ButtonType.Normal }) {
Image($rawfile('ic_public_connection_filled.svg'))
.size({
width: '24vp',
height: '24vp'
})
}
.width('36vp')
.height('36vp')
.backgroundColor(Color.White)
.borderRadius('10vp')
.onClick(() => {
this.distributedDeviceManagerDialogController.open()
})
}
.padding('5vp')
.width('90%')
}
build() {
Navigation() {
Column({ space: '20vp' }) {
Row({ space: '20vp' }) {
Text(`設(shè)備狀態(tài)`)
.fontSize('20vp')
.fontWeight(FontWeight.Bold)
Circle()
.width('25vp')
.height('25vp')
.fill(this.statusColor)
}
Row({ space: '20vp' }) {
Text(`對端設(shè)備狀態(tài)`)
.fontSize('20vp')
.fontWeight(FontWeight.Bold)
Circle()
.width('25vp')
.height('25vp')
.fill(this.distributedColor)
}
Text(`SessionID:${this.distributedObj.getSessionId()}`)
.fontSize('20vp')
.fontWeight(FontWeight.Bold)
Text(this.message)
.fontSize('20vp')
.fontWeight(FontWeight.Bold)
.maxLines(2)
Button('保存分布式數(shù)據(jù)對象')
.buttonStyles()
.onClick(() => {
this.distributedObj.saveDistributedObject()
})
Button('修改分布式數(shù)據(jù)對象')
.buttonStyles()
.onClick(() => {
this.distributedObj.updateDistributedObject()
})
Button('退出組網(wǎng)')
.buttonStyles()
.onClick(() => {
this.distributedObj.exit()
router.back()
})
}
.width('100%')
}
.width('100%')
.height('100%')
.mode(NavigationMode.Auto)
.titleMode(NavigationTitleMode.Mini)
.hideBackButton(true)
.title(this.navigationTitle())
}
}
function buttonStyles() {
(Button) .fontSize('20vp')
.width('60%')
.height('50vp')
}
(左右滑動查看更多)
現(xiàn)在,我們的頁面制作就完成啦,下面開始重頭戲——分布式數(shù)據(jù)對象開發(fā)流程
1、導(dǎo)入模塊
import distributedObject from '@ohos.data.distributedDataObject'
(左右滑動查看更多)
2、初始化distributedObject. DataObject對象
定義一個distributedObject. DataObject類型的變量。
mDistributedObject: distributedObject.DataObject
(左右滑動查看更多)
調(diào)用distributedObject. Create()函數(shù)創(chuàng)建一個distributedObject. DataObject對象,并將其返回給定義的變量mDistributedObject。
this.mDistributedObject = distributedObject.create(globalThis.context, {
name: 'jack',
age: 18,
isVis: false
})
(左右滑動查看更多)
在create()方法中存在兩個參數(shù),context和resource,context的類型為Context,resource類型為object,在這里我是在entryAbility.ts文件下的onWindowStageCreate()方法里面定義了一個全局變量globalThis.context。
globalThis.context = this.context
(左右滑動查看更多)
3、設(shè)置組網(wǎng)sessionId
this.mDistributedObject.setSessionId(this.mSessionId)
(左右滑動查看更多)
在setSessionId()函數(shù)中,參數(shù)sessionId為string類型,表示分布式對象組網(wǎng)唯一標識符,設(shè)置同步的sessionId,當可信組網(wǎng)中有多個設(shè)備時,多個設(shè)備間的對象如果設(shè)置為同一個sessionId,就能自動同步。
4、開啟設(shè)備狀態(tài)監(jiān)聽
globalThis.statusCallback = (sessionId: string, networkId: string, status: string) => {
AppStorage.Set('message', `組網(wǎng)設(shè)備狀況變更,id:${sessionId} status:${status} networkId:${networkId}`)
if (status == 'online') {
AppStorage.Set('distributedColor', '#ff4fc100')
} else if (status == 'offline') {
AppStorage.Set('distributedColor', '#ffff0000')
}
}
this.mDistributedObject.on("status",globalThis.statusCallback)
(左右滑動查看更多)
(sessionId: string,networkId: string, status: string)為callback回調(diào)函數(shù)返回的值,我們可以使用這些返回值判斷設(shè)備上下線狀態(tài),其中status參數(shù)返回值為online或者offline,表示設(shè)備對端設(shè)備上下線。
5、開啟分布式數(shù)據(jù)對象同步監(jiān)聽
globalThis.changeCallback = (sessionId: string, fields: Array<string>) => {
console.info('分布式數(shù)據(jù)對象發(fā)生變化')
if (fields != null && fields != undefined) {
AppStorage.Set('message', `data change:${fields} sessionId:${sessionId}`)
}
}
this.mDistributedObject.on("change",globalThis.changeCallback)
(左右滑動查看更多)
當同一組網(wǎng)內(nèi)分布式數(shù)據(jù)對象發(fā)生改變時,同一組網(wǎng)中的所有分布式數(shù)據(jù)對象同步發(fā)生變化,變化后的值為某一分布式數(shù)據(jù)對象改變后的值(sessionId: string, fields: Array)為callback回調(diào)函數(shù)返回值,其中,sessionId為組網(wǎng)唯一標識符,field為分布式數(shù)據(jù)對象的數(shù)據(jù)變更列表。
此時此刻,分布式數(shù)據(jù)對象就基本上開發(fā)完成啦。
如果有小伙伴想要修改分布式數(shù)據(jù)對象的屬性,可以直接修改
// @ts-ignore
this.mDistributedObject.name = 'lucy'
// @ts-ignore
this.mDistributedObject.age=25
(左右滑動查看更多)
注意:根據(jù)當前版本IDE的編碼插件情況,不能直接寫this.mDistributedObject.age = 25,此時咱們需要加上//@ts-ignore就可以啦。
最后,使用完分布式數(shù)據(jù)對象后大家要記得釋放資源哦(注銷所有監(jiān)聽,退出組網(wǎng)sessionId,將分布式數(shù)據(jù)對象設(shè)置為空值)
this.mDistributedObject.off("change")
this.mDistributedObject.off("status")
this.mDistributedObject.setSessionId()
this.mDistributedObject = null
this.mSessionId=null
(左右滑動查看更多)
如果有小伙伴有兩部或兩部以上的華為設(shè)備,可以將程序燒錄到設(shè)備中,體驗一下分布式數(shù)據(jù)對象能力的快樂~
-
應(yīng)用開發(fā)
+關(guān)注
關(guān)注
0文章
58瀏覽量
9357 -
HarmonyOS
+關(guān)注
關(guān)注
79文章
1973瀏覽量
30143
發(fā)布評論請先 登錄
相關(guān)推薦
評論