01、什么是分布式数据目标

在可信组网环境下,多个彼此组网认证的设备将各自创立的目标参加同一个sessionId,使得参加的多个数据目标之间能够同步数据,也就是说,当某一数据目标特点产生改动时,其他数据目标会检测到这一改动,一起将本身特点更新。此刻,该sessionId下的一切数据目标特点相同,这样的数据目标称之为分布式数据目标。此外,分布式数据目标能够被迫退出sessionId,当分布式数据目标退出sessionId后,该目标将检测不到其他目标的改动。

02、分布式数据目标才干

1、 分布式数据目标创立

2、 分布式数据目标查询

3、 分布式数据目标修正

4、 分布式数据目标删去

5、 分布式数据目标保存

6、 分布式数据目标订阅(数据改动,上下线)

7、分布式数据目标参加、退出分布式组网

03、条件预备

1、 开发东西:DevEcoStudio3.1.0.501

2、API:9

3、 SDK版别:3.2.12.5

04、创立一个新的项目

新建项目,选择API9版别,stage模型。

鸿蒙原生运用开发——分布式数据目标

05、权限请求

1、 运用到的权限

○ohos.permission.DISTRIBUTED_DATASYNC

○允许不同设备间的数据交换

○权限等级:normal

○授权办法:user_grant

○ACL使能:TRUE

2、配置文件声明

首要,在项目的模块级目录下找到并翻开module.json5文件,如下图:

鸿蒙原生运用开发——分布式数据目标
在module下的目标里增加如下声明:

鸿蒙原生运用开发——分布式数据目标

此刻,配置文件中的权限声明就完结了,但是,此刻我们还不能取得这些权限。因为ohos.permission.DISTRIBUTED_DATASYNC权限是ACL使能为TRUE的权限,需求在签名东西文件中阐明一下。

如何找到对应的签名东西文件呢?我们在安装DevEcoStudio的时候是下载好了OpenHarmony的SDK的,此刻在OpenHarmony文件夹中,翻开“SdkOpenHarmonySDK版别toolchainslib”该路径,此刻在lib文件夹中,我们能够找到两个json文件,分别为UnsgnedDebugProfileTemplate.json和UnsgnedReleasedProfileTemplate.json,点击并翻开这两个文件,增加如下权限:

鸿蒙原生运用开发——分布式数据目标

3、权限请求编码

在请求ohos.permission.DISTRIBUTED_DATASYNC权限时,其文档中将其标示为用户手动授权的权限,此刻需求我们动态请求权限,在项目中,我们新建一个ets文件,我这儿取名为RequestPermission.ets。

首要,导入以下包:

importabilityAccessCtrl,{Permissions}from'@ohos.abilityAccessCtrl';
importbundleManagerfrom'@ohos.bundle.bundleManager';
importcommonfrom'@ohos.app.ability.common';

获取拜访操控模块目标实例:

letatManager=abilityAccessCtrl.createAtManager();

编写如下办法(这儿运用的是异步函数):

exportasyncfunctioncheckAccessTokenID(permission:Array<Permissions>){
//获取运用程序的accessTokenID
lettokenId:number;
letgrantStatus:Array<abilityAccessCtrl.GrantStatus>=[]
try{
letbundleInfo:bundleManager.BundleInfo=awaitbundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);
letappInfo:bundleManager.ApplicationInfo=bundleInfo.appInfo;
tokenId=appInfo.accessTokenId;
}catch(err){
console.error(`getBundleInfoForSelffailed,codeis${err.code},messageis${err.message}`);
}
//校验运用是否被授予权限,若请求多个权限,建议循环检查多个权限
for(letindex=0;index<permission.length;index  ){
try{
grantStatus.push(awaitatManager.checkAccessToken(tokenId,permission[index]))
}catch(err){
console.error(`checkAccessTokenfailed,codeis${err.code},messageis${err.message}`);
}
}
returngrantStatus;
}
exportasyncfunctioncheckPermission(context:common.UIAbilityContext,permissions:Array<Permissions>){
letgrantStatus:Array<abilityAccessCtrl.GrantStatus>=awaitcheckAccessTokenID(permissions)
for(leti=0;i<grantStatus.length;i  ){
if(grantStatus[i]===abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED){
console.info(`${permissions[i].toString()}已授权`)
}else{
//请求权限
console.info('开始向用户请求权限')
requestPermissionFromUser(context,permissions)
}
}
}
exportasyncfunctionrequestPermissionFromUser(context:common.UIAbilityContext,permissions:Array<Permissions>){
//requestPermissionsFromUser会判断权限的授权状况来决定是否唤起弹窗
atManager.requestPermissionsFromUser(context,permissions).then((data)=>{
letgrantStatus:Array<number>=data.authResults
letlength:number=grantStatus.length
for(leti=0;i<length;i  ){
if(grantStatus[i]===0){
//用户授权,能够持续拜访目标操作
console.info(`${permissions[i].toString()}权限请求成功`)
}else{
//用户拒绝授权,提示用户有必要授权才干拜访当时页面的功用,并引导用户到系统设置中翻开相应的权限
console.info(`${permissions[i].toString()}权限请求被用户拒绝`)
}
}
//授权成功
})
}

此刻,我们请求权限的办法就算编写完结了,在运用进口,即EntryAbility.ts文件中的

onCreate(want:Want,launchParam:AbilityConstant.LaunchParam)

办法中回调权限请求函数:

requestPermissionFromUser(this.context,PERMISSIONS)

其间,PERMISSIONS界说如下:

constPERMISSIONS:Array=[‘ohos.permission.DISTRIBUTED_DATASYNC’]

到此,我们的权限请求就算完完全全完结啦,当用户第一次安装并翻开运用的时候,运用会向用户经过弹窗形式请求权限,用户点击授权即可赋予运用相应的权限啦~

06、上手分布式数据目标代码开发

登录了同一华为帐号的HarmonyOS设备已经默认了进行了组网认证,所以在进行分布式数据目标开发之前无需再进行多设备组网认证这一阶段的开发,开发变得相对简单了起来。首要,我们制造一个简易UI界面(UI界面仅供参考),如下图所示:

鸿蒙原生运用开发——分布式数据目标

相信关于有HarmonyOS开发经验的小伙伴们来说这样的UI界面制造并不困难,其间赤色圆点、绿色圆点为设备状况,当设备状况产生改动如下线时,颜色变为赤色,UI界面代码如下:

importrouterfrom'@ohos.router'
import{DistributedDeviceManageFunc}from'../modules/DistributedDeviceManager/DistributedDeviceManagerFunctions'
importDistributedObjectFuncfrom'../modules/DistributedObject/DistributedObjectFunctions'
import{ContinuationDeviceManagerDialog}from'../view/ContinuationDeviceManagerDialog'
import{DistributedDeviceManagerDialog}from'../view/DistributedDeviceManagerDialog'
AppStorage.SetOrCreate('distributedDeviceList',[])
AppStorage.SetOrCreate('message','分布式数据目标Demo测试')
AppStorage.SetOrCreate('statusColor','#ff4fc100')
AppStorage.SetOrCreate('distributedColor','#ffff0000')
@Entry
@Component
structDistributedObjectDemo{
@StorageLink('message')message:string=''
@StorageLink('statusColor')statusColor:string=''
@StorageLink('distributedColor')distributedColor:string=''
@StorageLink('distributedObj')distributedObj:DistributedObjectFunc=newDistributedObjectFunc()
@Builder
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('分布式数据目标测试')
.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(`设备状况`)
.fontSize('20vp')
.fontWeight(FontWeight.Bold)
Circle()
.width('25vp')
.height('25vp')
.fill(this.statusColor)
}
Row({space:'20vp'}){
Text(`对端设备状况`)
.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('保存分布式数据目标')
.buttonStyles()
.onClick(()=>{
this.distributedObj.saveDistributedObject()
})
Button('修正分布式数据目标')
.buttonStyles()
.onClick(()=>{
this.distributedObj.updateDistributedObject()
})
Button('退出组网')
.buttonStyles()
.onClick(()=>{
this.distributedObj.exit()
router.back()
})
}
.width('100%')
}
.width('100%')
.height('100%')
.mode(NavigationMode.Auto)
.titleMode(NavigationTitleMode.Mini)
.hideBackButton(true)
.title(this.navigationTitle())
}
}
@Extend(Button)functionbuttonStyles(){
.fontSize('20vp')
.width('60%')
.height('50vp')
}

现在,我们的页面制造就完结啦,下面开始重头戏——分布式数据目标开发流程

1、导入模块

importdistributedObjectfrom'@ohos.data.distributedDataObject'

2、初始化distributedObject.DataObject目标

界说一个distributedObject.DataObject类型的变量

mDistributedObject:distributedObject.DataObject

调用distributedObject.Create()函数创立一个distributedObject.DataObject目标,并将其回来给界说的变量mDistributedObject。

this.mDistributedObject=distributedObject.create(globalThis.context,{
name:'jack',
age:18,
isVis:false
})

在create()办法中存在两个参数,context和resource,context的类型为Context,resource类型为object,在这儿我是在entryAbility.ts文件下的onWindowStageCreate()办法里面界说了一个全局变量globalThis.context。

globalThis.context=this.context

3、设置组网sessionId

this.mDistributedObject.setSessionId(this.mSessionId)

在setSessionId()函数中,参数sessionId为string类型,表明分布式目标组网仅有标识符,设置同步的sessionId,当可信组网中有多个设备时,多个设备间的目标假如设置为同一个sessionId,就能主动同步。

4、敞开设备状况监听

globalThis.statusCallback=(sessionId:string,networkId:string,status:string)=>{
AppStorage.Set('message',`组网设备状况改动,id:${sessionId}status:${status}networkId:${networkId}`)
if(status=='online'){
AppStorage.Set('distributedColor','#ff4fc100')
}elseif(status=='offline'){
AppStorage.Set('distributedColor','#ffff0000')
}
}
this.mDistributedObject.on("status",globalThis.statusCallback)

(sessionId:string,networkId:string,status:string)为callback回调函数回来的值,我们能够运用这些回来值判断设备上下线状况,其间status参数回来值为online或者offline,表明设备对端设备上下线。

5、敞开分布式数据目标同步监听

globalThis.changeCallback=(sessionId:string,fields:Array<string>)=>{
console.info('分布式数据目标产生变化')
if(fields!=null&&fields!=undefined){
AppStorage.Set('message',`datachange:${fields}sessionId:${sessionId}`)
}
}
this.mDistributedObject.on("change",globalThis.changeCallback)

当同一组网内分布式数据目标产生改动时,同一组网中的一切分布式数据目标同步产生变化,变化后的值为某一分布式数据目标改动后的值(sessionId:string,fields:Array)为callback回调函数回来值,其间,sessionId为组网仅有标识符,field为分布式数据目标的数据改动列表。

此刻此刻,分布式数据目标就基本上开发完结啦。

假如有小伙伴想要修正分布式数据目标的特点,能够直接修正

//@ts-ignore
this.mDistributedObject.name='lucy'
//@ts-ignore
this.mDistributedObject.age=25

注意:依据当时版别IDE的编码插件情况,不能直接写this.mDistributedObject.age=25,此刻我们需求加上//@ts-ignore就能够啦。

最终,运用完分布式数据目标后我们要记得释放资源哦(刊出一切监听,退出组网sessionId,将分布式数据目标设置为空值)

this.mDistributedObject.off("change")
this.mDistributedObject.off("status")
this.mDistributedObject.setSessionId()
this.mDistributedObject=null
this.mSessionId=null

假如有小伙伴有两部或两部以上的华为设备,能够将程序烧录到设备中,体会一下分布式数据目标才干的快乐~