鸿蒙原生应用开发——分布式数据对象

01、什么是分布式数据对象

在可信组网环境下,多个相互组网认证的设备将各自创建的对象加入同一个 sessionId,使得加入的多个数据对象之间可以同步数据,也就是说,当某一数据对象属性发生变更时,其他数据对象会检测到这一变更,同时将自身属性更新。此时,该 sessionId 下的所有数据对象属性相同,这样的数据对象称之为分布式数据对象。此外,分布式数据对象可以被动退出 sessionId,当分布式数据对象退出 sessionId 后,该对象将检测不到其他对象的变更。

02、分布式数据对象能力

1、  分布式数据对象创建

2、  分布式数据对象查询

3、  分布式数据对象修改

4、  分布式数据对象删除

5、  分布式数据对象保存

6、  分布式数据对象订阅(数据变更,上下线)

7、分布式数据对象加入、退出分布式组网

03、前提准备

1、  开发工具:DevEco Studio 3.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 的权限,需要在签名工具文件中说明一下。

如何找到对应的签名工具文件呢?我们在安装 DevEco Studio 的时候是下载好了 OpenHarmony 的 SDK 的,此时在 OpenHarmony 文件夹中,打开 “Sdk\OpenHarmony SDK 版本\toolchains\lib” 该路径,此时在 lib 文件夹中,咱们可以找到两个 json 文件,分别为 UnsgnedDebugProfileTemplate.json 和 UnsgnedReleasedProfileTemplate.json,点击并打开这两个文件,添加如下权限:

3、权限申请编码

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

首先,导入以下包:

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

获取访问控制模块对象实例:

let atManager = abilityAccessCtrl.createAtManager();

编写如下方法(这里使用的是异步函数):

export async function checkAccessTokenID(permission: Array<Permissions>) {// 获取应用程序的accessTokenIDlet tokenId: number;let grantStatus: Array<abilityAccessCtrl.GrantStatus> = []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}`);}// 校验应用是否被授予权限,若申请多个权限,建议循环检查多个权限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<Permissions>) {let grantStatus: Array<abilityAccessCtrl.GrantStatus> = await checkAccessTokenID(permissions)for (let i = 0; i < grantStatus.length; i++) {if (grantStatus[i] === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {console.info(`${permissions[i].toString()} 已授权`)} else {//申请权限console.info('开始向用户申请权限')requestPermissionFromUser(context, permissions)}}
}
export async function requestPermissionFromUser(context: common.UIAbilityContext, permissions: Array<Permissions>) {// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗atManager.requestPermissionsFromUser(context, permissions).then((data) => {let grantStatus: Array<number> = data.authResultslet length: number = grantStatus.lengthfor (let i = 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 定义如下:const PERMISSIONS:Array<Permissions>=['ohos.permission.DISTRIBUTED_DATASYNC']

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

06、上手分布式数据对象代码开发

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

相信对于有 HarmonyOS 开发经验的小伙伴们来说这样的 UI 界面制作并不困难,其中红色圆点、绿色圆点为设备状态,当设备状态发生改变如下线时,颜色变为红色,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', '分布式数据对象Demo测试')
AppStorage.SetOrCreate('statusColor', '#ff4fc100')
AppStorage.SetOrCreate('distributedColor', '#ffff0000')@Entry
@Component
struct DistributedObjectDemo {@StorageLink('message') message: string = ''@StorageLink('statusColor') statusColor: string = ''@StorageLink('distributedColor') distributedColor: string = ''@StorageLink('distributedObj') distributedObj: DistributedObjectFunc = new DistributedObjectFunc()@BuildernavigationTitle() {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) function buttonStyles() {.fontSize('20vp').width('60%').height('50vp')
}

现在,我们的页面制作就完成啦,下面开始重头戏——分布式数据对象开发流程

1、导入模块

import distributedObject from '@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')} else if (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', `data change:${fields} sessionId:${sessionId}`)  }}this.mDistributedObject.on("change", globalThis.changeCallback)

当同一组网内分布式数据对象发生改变时,同一组网中的所有分布式数据对象同步发生变化,变化后的值为某一分布式数据对象改变后的值(sessionId: string, fields: Array<string>)为 callback 回调函数返回值,其中,sessionId 为组网唯一标识符,field 为分布式数据对象的数据变更列表。

此时此刻,分布式数据对象就基本上开发完成啦。

如果有小伙伴想要修改分布式数据对象的属性,可以直接修改

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

注意:根据当前版本 IDE 的编码插件情况,不能直接写 this.mDistributedObject.age = 25,此时咱们需要加上// @ts-ignore 就可以啦。

最后,使用完分布式数据对象后大家要记得释放资源哦(注销所有监听,退出组网 sessionId,将分布式数据对象设置为空值)

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

如果有小伙伴有两部或两部以上的华为设备,可以将程序烧录到设备中,体验一下分布式数据对象能力的快乐~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/212751.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Theamleaf导出pdf模版编写(原始th/td编写表格)

需求&#xff1a;简单的theamleaf编写表格就是简单的th/td&#xff0c;新需求是导出的模版是学员table表&#xff0c;每个项目的学员数量是不定的&#xff0c;所以用到 <tr th:each"item,start:${studentList}"> 所有代码&#xff1a; <!DOCTYPE html>…

离线数仓构建案例一

数据采集 日志数据&#xff08;文件&#xff09;到Kafka 自己写个程序模拟一些用户的行为数据&#xff0c;这些数据存在一个文件夹中。 接着使用flume监控采集这些文件&#xff0c;然后发送给kafka中待消费。 1、flume采集配置文件 监控文件将数据发给kafka的flume配置文件…

GateWay的路由与全局过滤器

1.断言工厂 我们在配置文件中写的断言规则只是字符串&#xff0c;这些字符串会被Predicate Factory读取并处理&#xff0c;转变为路由判断的条件 例如Path/user/**是按照路径匹配&#xff0c;这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePr…

Linux查看命令的绝对路径

linux查看命令的绝对路径 在Linux中&#xff0c;可以使用以下命令来查看命令的绝对路径&#xff1a; 1、which 命令名 例如&#xff0c;要查看chronyc命令的绝对路径&#xff0c;可以运行&#xff1a; which chronyc 2、whereis 命令名 例如&#xff0c;要查看chronyc命令…

thinkphp lists todo

来由&#xff1a; 数据库的这个字段我想返回成&#xff1a; 新奇的写法如下&#xff1a; 逻辑层的代码&#xff1a; public function goodsDetail($goodId){$detail $this->good->where(id, $goodId)->hidden([type_params,user_id])->find();if (!$detail) {ret…

数字化和数智化一字之差,究竟有何异同点?

在2023杭州云栖大会的一展台内&#xff0c;桌子上放着一颗番茄和一个蛋糕&#xff0c;一旁的机器人手臂融入“通义千问”大模型技术后&#xff0c;变得会“思考”&#xff1a;不仅能描述“看”到了什么&#xff0c;还能确认抓取的是番茄而不是蛋糕。 “传统的机械臂通常都只能基…

【C语言】7-32 刮刮彩票 分数 20

7-32 刮刮彩票 分数 20 全屏浏览题目 切换布局 作者 DAI, Longao 单位 杭州百腾教育科技有限公司 “刮刮彩票”是一款网络游戏里面的一个小游戏。如图所示&#xff1a; 每次游戏玩家会拿到一张彩票&#xff0c;上面会有 9 个数字&#xff0c;分别为数字 1 到数字 9&#xf…

windows系统nodeJs报错node-sass npm ERR! command failed

报错信息 npm WARN deprecated request2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated tar2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asa…

利用R语言heatmap.2函数进行聚类并画热图

数据聚类然后展示聚类热图是生物信息中组学数据分析的常用方法&#xff0c;在R语言中有很多函数可以实现&#xff0c;譬如heatmap,kmeans等&#xff0c;除此外还有一个用得比较多的就是heatmap.2。最近在网上看到一个笔记文章关于《一步一步学heatmap.2函数》&#xff0c;在此与…

vscode如何在没有网络的情况下安装插件

vscode如何在没有网络的情况下安装插件 start 遇到没有网络的电脑&#xff0c;无法直接从插件市场安装vscode的插件。写一下 vscode 插件离线安装的方法. 解决方案 目标电脑没有可以安装插件的网络&#xff0c;那我们只能在有网络的环境下载好我们的插件。然后拷贝软件到无…

智能优化算法应用:基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于战争策略算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.战争策略算法4.实验参数设定5.算法结果6.参考…

服务器数据恢复—重装系统导致XFS文件系统分区丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 服务器使用磁盘柜RAID卡搭建了一组riad5磁盘阵列。服务器上层分配了一个LUN&#xff0c;划分了两个分区&#xff1a;sdc1分区和sdc2分区。通过LVM扩容的方式&#xff0c;将sdc1分区加入到了root_lv中&#xff1b;sdc2分区格式化为XFS文件系统。…

【洛谷】更换头像

错误展示 今天换头像的时候发现一直换不了&#xff0c;即使显示修改成功&#xff0c;然后我等了半个多小时也还没换好 解决办法 上传成功头像后&#xff0c;按ctrl F5 结果 更新成功&#xff01;

智能优化算法应用:基于侏儒猫鼬算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于侏儒猫鼬算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于侏儒猫鼬算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.侏儒猫鼬算法4.实验参数设定5.算法结果6.参考…

Clion自定义管理和配置软件构建过程的工具(代替CMake)构建程序

在公司由于需要x86环境和其他arm环境&#xff0c;同时需要使用公司自定义的mine_x86或者mine_orin对代码进行编译。 编译命令如下mine_x86 build -Dlocal1 -j8,为使用Clion对程序进行调试&#xff0c;需要对程序进行设置。方便调试代码时能够断点查看变量。尝试了很多次&#…

区块链实验室(28) - 拜占庭节点劫持区块链仿真

在以前的FISCO环境中仿真拜占庭节点攻击区块链网络。该环境共有100个节点&#xff0c;采用PBFT作为共识机制&#xff0c;节点编号分别为&#xff1a;Node0&#xff0c;Node&#xff0c;… &#xff0c;Node99。这100个节点的前2010区块完全相同&#xff0c;自区块2011开始分叉。…

为“异常”努力是值得的

异常是OO语言处理错误的方式,在C中&#xff0c;鼓励使用异常。侯捷再书中谈起异常&#xff0c;“十年前撰写“未将异常考虑在内的”函数是为一种美好实践&#xff0c;而今我们致力于写出“异常安全码”。”可见异常安全的重要。 说起异常安全&#xff0c;首先就要是异常的出现…

Kafka中的auto-offset-reset配置

Kafka这个服务在启动时会依赖于Zookeeper&#xff0c;Kafka相关的部分数据也会存储在Zookeeper中。如果kafka或者Zookeeper中存在脏数据的话&#xff08;即错误数据&#xff09;&#xff0c;这个时候虽然生产者可以正常生产消息&#xff0c;但是消费者会出现无法正常消费消息的…

linux高级篇基础理论七(Tomcat)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xff1a;云计算技…

AWS攻略——创建VPC

文章目录 创建一个可以外网访问的VPCCIDR主路由表DestinationTarget 主网络ACL入站规则出站规则 子网创建EC2测试连接创建互联网网关&#xff08;IGW&#xff09;编辑路由表 知识点参考资料 在 《AWS攻略——VPC初识》一文中&#xff0c;我们在AWS默认的VPC下部署了一台可以SS…