HC 2024 开发者布道师交流区分布式作品技术分享帖

举报
王天一 发表于 2024/09/29 17:39:09 2024/09/29
【摘要】 本作品的工作始于第一届OpenHarmony竞赛训练营行业使能赛题(题目十:OpenHarmony阅读器.md · OpenHarmony竞赛训练营),在参加HC2024学生布道师展区之前,在原作品的基础上添加了OpenHarmony分布式软总线能力,进一步提升了用户的阅读体验、体现了鸿蒙系统的重要特性之一——“硬件互助、资源共享”。

HC分布式作品技术分享帖

作者:兰州大学 学生开发者布道师 王天一、聂嘉一

1.OpenHarmony阅读器及分布式能力介绍

本作品的工作始于第一届OpenHarmony竞赛训练营行业使能赛题(题目十:OpenHarmony阅读器.md · OpenHarmony竞赛训练营),在参加HC2024学生布道师展区之前,在原作品的基础上添加了OpenHarmony分布式软总线能力,进一步提升了用户的阅读体验、体现了鸿蒙系统的重要特性之一——“硬件互助、资源共享”。

本作品主要使用了以下技术元素来实现不同设备间的组网与通信、同步拉起与数据共享:

  1. 使用分布式设备管理能力接口(设备管理),实现设备之间的distributedDataObject对象的数据传输交互@ohos.distributedDeviceManager
  2. 使用分布式数据管理接口@ohos.data.distributedData
  3. 使用权限管理能力@ohos.abilityAccessCtrl
  4. 使用分布式数据对象接口@ohos.data.distributedDataObject

本作品的分布式交互效果如下列链接中的视频所示:。

2.OpenHarmony阅读器实现

约束与限制

1.本示例仅支持标准系统上运行。

2.本示例为Stage模型,已适配API version 10版本SDK,版本号:4.0.10.13,镜像版本号:OpenHarmony4.0.10.13。

3.本示例需要使用DevEco Studio 3.1 Beta2 (Build Version: 3.1.0.400, built on April 7, 2023)及以上版本才可编译运行。

4.本示例需要使用@ohos.distributedDeviceManager系统权限的系统接口。使用Full SDK时需要手动从镜像站点获取,并在DevEco Studio中替换,具体操作可参考替换指南

5.本示例所配置的权限均为system_basic或system_core级别(相关权限级别可通过权限定义列表查看),需要手动配置对应级别的权限签名(具体操作可查看自动化签名方案)。

6.本示例类型为系统应用,需要手动配置对应级别的应用类型(“app-feature”: “hos_system_app”)。具体可参考profile配置文件bundle-info对象内部结构

本作品的ArkUI实现重点为分布式连接界面和阅读界面。

使用说明

  1. 启动应用,选择允许授权后,进入首页的分布式连接界面:

  1. 点击右上角按钮可以连接组网设备,选择设备后进行连接,连接成功后两个设备上首页状态均显示绿色,每次连接其他设备,界面会清空已保存的书籍记录。

  2. 点击添加按钮进入添加界面,可以编辑标题、介绍,点击确定按钮添加这条记录。

  3. 点击清除按钮清除所有书籍记录。

  4. 点击已经添加的备忘录可以进入编辑界面更新书籍记录,编辑完成后点击提交按钮更新书籍记录。

  5. 两台设备连接成功后步骤2、3、4的操作会同步到另一台设备上。

  6. 如选择开始阅读,则进入界面:

    1. 点击右上角按钮可以连接组网设备,选择设备后进行连接,连接成功后两个设备上首页状态均显示绿色。
    2. 两台设备连接成功后进行的翻页操作会同步到另一台设备上。
    3. 点击back按钮,则回退到首页。

相关概念

分布式数据对象:组网内的设备,通过创建相同sessionId的分布式数据对象,修改分布式对象时,对端设备可以监听到数据变化并获取到新的数据,从而实现不同设备间的数据交换。

3.工程目录

entry/src/main/ets/
|---pages
|   |---index.ets                           // 首页
|   |---SplashPages.ets                     // 应用启动动画页面
|   |---IndexNote.ets                       // 分布式连接页面
|   |---Read.ets                            // 阅读页面
|---MainAbility                                    
|   |---MainAbility.ts                      // 请求用户授权“多设备协同”能力
|---model                                  
|   |---Const.ts                            // 静态资源模块(书籍标记颜色的图片资源)
|   |---DistributedObjectModel.ts           // 分布式书籍数据对象类
|   |---Note.ts                             // 书籍对象操作类
|   |---RemoteDeviceModel.ts                // 远程设备操作类
|---common                                    
|   |---BasicDataSource.ets                 // 初始化数据模块
|   |---NoteItem.ets                        // 书籍列表模块
|   |---DeviceDialog.ets                    // 分布式设备列表弹窗
|   |---TitleBar.ets                        // 菜单栏模块

页面代码示例1:启动动画界面

.\pages\SplashPage.ets

代码功能

  1. 存储初始化:初始化了应用的持久化存储,将 token 设置为空字符串,并设置 currentTabIndex 的值为 0。可以通过改变currentTabIndex的值来实现页面底部导航栏页面的切换。
  2. 动画过渡:当页面显示时(onPageShow 方法),使用动画效果展示 Logo 和应用名称,然后通过定时器延迟一段时间后跳转到另一个页面。
  3. 页面构建:使用 build 方法来构建用户界面,包括一个条件渲染的 Logo 和应用名称,以及一个固定的底部文本。

代码解析

  1. 页面显示处理

    onPageShow(){
      animateTo({
        duration: 1000,
        onFinish: () => {
          setTimeout(() => {
            router.replaceUrl({ url: 'pages/IndexNote' });  // 切换页面,且不能返回
          }, 200);
        }
      }, () => {
        this.flag = true;
      });
    }
    

    当页面显示时,执行动画效果,动画结束后延迟 200 毫秒执行页面跳转。这里使用 replaceUrl 而不是普通的 pushUrl,使用户从新页面返回时不会再次触发该启动动画。

  2. 页面构建逻辑

    build() {
      Column() {
        if (this.flag) {
          Image($r('app.media.ic_logo_lzu'))
            .logoStyle()
            .transition({ type: TransitionType.Insert, opacity: 0, translate: { x: -150 } });
          Text("开源鸿蒙阅读器demo")
            .titleStyle()
            .transition({ type: TransitionType.Insert, opacity: 0, translate: { x: 150 } });
        }
        Blank()
        Text("OpenHarmony Project")  // 最底部
          .footerStyle();
      }.bgStyle();
    }
    

    使用条件语句来根据 flag 的值决定是否显示 Logo 和应用名称。此外,还设置了动画过渡效果来平滑地展示这些元素,底部有一个固定的文本 “OpenHarmony Project”。

**页面代码示例2:分布式连接 **

.\pages\IndexNote.ets

代码功能

  1. 设备管理和跨设备同步:使用 DistributedObjectModel 进行跨设备的数据共享,并且有状态变更回调机制。
  2. 设备选择与启动:允许用户选择一个远程设备,并启动目标设备上的能力(相当于应用中的某个功能模块)。
  3. 笔记数据展示与操作:展示书籍列表,并提供添加和清除笔记的功能。
  4. 状态指示:展示当前设备的在线状态。

代码解析

  1. 设备选择与启动

    onSelectedDevice = (selectedIndex: number) => {
      this.selectedIndex = selectedIndex;
      Logger.info(TAG, 'start ability ......');
      if (RemoteDeviceModel === null || RemoteDeviceModel.discoverDevices.length <= 0) {
        Logger.info(TAG, `start ability device:${JSON.stringify(this.devices)}`);
        this.startAbility(this.devices[this.selectedIndex].networkId as string);
        this.clearSelectState();
        return;
      }
      Logger.info(TAG, 'start ability, needAuth');
      RemoteDeviceModel.authenticateDevice(this.devices[this.selectedIndex], (device: deviceManager.DeviceBasicInfo) => {
        Logger.info(TAG, 'auth and online finished');
        this.startAbility(device.networkId);
      })
      Logger.info(TAG, 'start ability2 ......');
      this.clearSelectState();
    }
    

    当用户选择了一个设备后,会调用 startAbility 方法来启动远程设备的能力。如果设备列表为空或者不存在,则直接启动;否则需要先认证设备。

  2. 笔记数据展示与操作

    List({ space: 10 }) {
      LazyForEach(this.noteDataSource, (item: Note, index) => {
        ListItem() {
          NoteItem({ note: item, index: index })
            .id(`${item.title}`)
        }
      }, (item: Note) => JSON.stringify(item))
    }
    

    这部分代码展示了笔记列表,并且使用了懒加载机制来提高性能。

  3. 状态指示

    Row() {
      Text("连接状态 ")
        .fontWeight(FontWeight.Bold)
        .height(35)
        .fontSize(18)
      Image(this.isOnline ? $r('app.media.green') : $r('app.media.red'))
        .size({ width: 20, height: 20 })
        .objectFit(ImageFit.Contain)
    }
    

    这部分代码展示了当前设备的连接状态,使用绿色或红色图标表示在线或离线状态。

  4. 页面构建逻辑

    build() {
      Column() {
        // 状态栏和其他UI元素
        ...
        // 笔记列表
        List({ space: 10 }) {
          LazyForEach(this.noteDataSource, (item: Note, index) => {
            ListItem() {
              NoteItem({ note: item, index: index })
                .id(`${item.title}`)
            }
          }, (item: Note) => JSON.stringify(item))
        }
        .width('95%')
        .margin(10)
        .layoutWeight(1)
    
        // 清除笔记按钮
        Column() {
          Image($r('app.media.clear'))
            .size({ width: 20, height: 20 })
          Text($r('app.string.clear'))
            .fontColor(Color.Red)
            .fontSize(20)
        }.layoutWeight(1)
        .id('clearNote')
        .onClick(() => {
          Logger.info(TAG, 'clear notes');
          this.noteDataSource.dataArray = [];
          this.noteDataSource.notifyDataReload();
          this.globalObject.clear();
          AppStorage.SetOrCreate('sessionId', this.sessionId);
        })
    
        // 添加笔记按钮
        Column() {
          Image($r('app.media.add'))
            .size({ width: 20, height: 20 })
          Text($r('app.string.add'))
            .fontColor(Color.Black)
            .fontSize(20)
        }.layoutWeight(1)
        .id('addNote')
        .onClick(() => {
          router.pushUrl({
            url: 'pages/Edit',
            params: {
              note: new Note('', '', '', -1, 0),
              isAdd: true
            }
          })
        })
      }
      .width('100%')
      .height('100%')
    }
    

    页面构建部分主要负责创建 UI 元素,包括顶部的状态栏、笔记列表以及底部的操作按钮(清除笔记和添加笔记)。每个元素都有特定的样式配置,并且添加了点击事件处理器以实现相应的功能。

相关权限

允许不同设备间的数据交换:ohos.permission.DISTRIBUTED_DATASYNC

允许系统应用获取分布式设备的认证组网能力:ohos.permission.ACCESS_SERVICE_DM

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。