0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

HarmonyOS开发者 来源:HarmonyOS开发者 作者:HarmonyOS开发者 2023-12-07 21:40 次阅读
# 开发者说 #

【开发者说】栏目是为HarmonyOS开发者提供的展示和分享平台,在这里,大家可以发表自己的技术洞察和见解,也可以展示自己的开发心得和成果。

欢迎大家积极投稿,后台回复【投稿】,即可获得投稿渠道。期待你们的分享~

01

什么是分布式数据对象

可信组网环境下,多个相互组网认证的设备将各自创建的对象加入同一个sessionId,使得加入的多个数据对象之间可以同步数据,也就是说,当某一数据对象属性发生变更时,其他数据对象会检测到这一变更,同时将自身属性更新。

此时,该sessionId下的所有数据对象属性相同,这样的数据对象称之为分布式数据对象。此外,分布式数据对象可以被动退出sessionId,当分布式数据对象退出sessionId后,该对象将检测不到其他对象的变更。

02

分布式数据对象能力

1、分布式数据对象创建2、分布式数据对象查询3、分布式数据对象修改4、分布式数据对象删除5、分布式数据对象保存6、分布式数据对象订阅(数据变更,上下线)

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

03

前提准备

1、开发工具:DevEco Studio 3.1.0.501

2、API9

3、SDK版本3.2.12.504

创建一个新的项目

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

wKgZomVys6-AG0_1AAEXQ0yjzBI034.png05

权限申请

1、使用到的权限
  • ohos.permission.DISTRIBUTED_DATASYNC
  • 允许不同设备间的数据交换
  • 权限级别:normal
  • 授权方式:user_grant
  • ACL使能:TRUE

2、配置文件申明

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

wKgZomVys6-Ac2AbAANDz2HtWlk721.png

在module下的对象里添加如下申明:

wKgZomVys6-ADikuAAB7_cWlh4w151.png

此时,配置文件中的权限申明就完成了,但是,此时我们还不能获得这些权限。由于ohos.permission.DISTRIBUTED_DATASYNC权限是ACL使能为TRUE的权限,需要在签名工具文件中说明一下。

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

wKgaomVys6-AEVe-AAB8i3XVu2I513.png

3、权限申请编码

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

首先,导入以下包:

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

(左右滑动查看更多)

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

let atManager = abilityAccessCtrl.createAtManager();

(左右滑动查看更多

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

export async function checkAccessTokenID(permission: Array) {
  // 获取应用程序的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}`);
  }
  // 校验应用是否被授予权限,若申请多个权限,建议循环检查多个权限
  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()} 已授权`)
    } else {
      //申请权限
      console.info('开始向用户申请权限')
      requestPermissionFromUser(context, permissions)
    }
  }
}
export async function requestPermissionFromUser(context: common.UIAbilityContext, permissions: Array) {
  // requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
  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) {
        // 用户授权,可以继续访问目标操作
        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=['ohos.permission.DISTRIBUTED_DATASYNC']

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

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

登录了同一华为帐号的HarmonyOS设备已经默认了进行了组网认证,所以在进行分布式数据对象开发之前无需再进行多设备组网认证这一阶段的开发,开发变得相对简单了起来。

首先,咱们制作一个简易UI界面(UI界面仅供参考),如下图所示:

wKgZomVys6-ADbPyAACVnGtFZXo950.png

相信对于有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()


  @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) 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)为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

(左右滑动查看更多

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


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 应用开发
    +关注

    关注

    0

    文章

    52

    浏览量

    9141
  • HarmonyOS
    +关注

    关注

    79

    文章

    1861

    浏览量

    29267
收藏 人收藏

    评论

    相关推荐

    鸿蒙千帆起】《开心消消乐》完成鸿蒙原生应用开发,创新多端联动用户体验

    更优质的用户体验,基于强大的 AI 能力还可以实现精准识别、精确投放,为伙伴提供新流量,并共享全场景服务分发,助力生态共赢。数据显示,截至今年 8 月份,鸿蒙生态的设备数已超过 7 亿,鸿蒙生态
    发表于 01-03 10:22

    HarmonyOS SDK,助力开发者打造焕然一新的鸿蒙原生应用

    六大领域的开发能力,为开发者带来简洁、高效的开发体验,开发者只需通过 API 调用即可实现丰富的鸿蒙
    发表于 01-19 10:31

    鸿蒙系统优缺点,能否作为开发者选择

    星河版已经是纯血鸿蒙,但是它的发展一些周期。生态圈的建立难度大,各大厂商加入鸿蒙原生开发需要时间累积。 鸿蒙
    发表于 02-16 21:00

    鸿蒙开发者预览版如何?

    原生智能、原生互联,6大极致原生体验。 我初步阅读了鸿蒙的源码后,基本上可以确定是全自研底座,已经看不到Android的身影了。作为开发者
    发表于 02-17 21:54

    华为鸿蒙—时代的开启

    总线技术”通过公共通信平台,分布式数据管理,分布式能力调度和虚拟外设四大能力。将相应分布式应用的底层技术实现难度对应用开发者屏蔽,使
    发表于 09-03 11:19

    HarmonyOS应用开发-分布式设计

    不同终端设备之间的极速连接、硬件协同、资源共享,为用户提供最佳的场景体验。分布式设计指南可以帮助应用开发者了解如何充分发挥“One Super Device”的能力,提供独特的跨设备交互体验。说明:本设计指南后续举例中将包括手机、智慧屏、手表等多种设备,其中手机均指 EM
    发表于 09-22 17:11

    HarmonyOS分布式数据库,为啥这么牛?

    HarmonyOS 2.0 重要的三大核心技术底座之一:HarmonyOS 分布式数据管理平台,也同步对开发者进行了细致的宣讲,我作为开发者有幸参与聆听了相关议题介绍。
    发表于 11-19 15:38

    绝对干货!HarmonyOS开发者日资料全公开,鸿蒙开发者都在看

    应用开发模板,分布式调试调优,上架开发规范解读等。6、HarmonyOS 分布式应用框架深入解读:该主题深度解析HarmonyOS分布式应用
    发表于 08-04 14:36

    鸿蒙、iOS、安卓的开发者数量,APP数量大对比,差距有多大呢?

    ,只要开发者数量多了,APP就多了,生态就起来了。那么我们对比一下当前华为鸿蒙、苹果iOS、谷歌安卓的开发者数量、APP数量,大家来看一看,差距到底有多大。先说苹果,按照苹果今年在WWDC上公布的
    发表于 08-30 14:27

    HarmonyOS分布式应用框架深入解读

    着,一般默默地为开发者和用户服务。基础服务层:包括分布式调度管理、分布式数据管理、分布式硬件管理、分布式
    发表于 11-22 15:15

    如何高效完成HarmonyOS分布式应用测试?

    作者:liuxun,HarmonyOS测试架构师HarmonyOS是新一代的智能终端操作系统,给开发者提供了设备发现、设备连接、跨设备调用等丰富的分布式API。随着越来越多的开发者投入到
    发表于 12-13 18:07

    分布式数据对象:超级终端的"全局变量"

    设备访问这些变量就能像操作本地变量一样,数据就能够自动高效、便捷地实现多端同步了。为此,本次 OpenHarmony v3.1 Release 版本新增了分布式数据对象特性。
    发表于 06-09 15:18

    开发者】XstoryMaker快速书写剧本场景动画

    。 我在开发XstoryMaker关于视觉小说的分布式流转的时候根本没有感受到这是两台设备在做数据传输的开发,两个端的开发代码只需要按照一个
    发表于 09-14 12:04

    鸿蒙原生应用/元服务开发-开发者如何进行真机测试

    前提条件:已经完成鸿蒙原生应用/元服务开发,已经能相对熟练使用DevEco Studio,开发者自己有鸿蒙4.0及以上的真机设备。 真机测试
    发表于 11-30 09:46

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

    01、什么是分布式数据对象 在可信组网环境下,多个相互组网认证的设备将各自创建的对象加入同一个 sessionId,使得加入的多个数据
    发表于 12-08 10:01