用ArkUI实现碰一碰配网、设备控制

系统
今天来尝试下eTS开发,但是ArkUI只有在API7上才能支持,目前绝大多数手机还都是API6,所以配网部分只能先代码模拟测试。

[[442569]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

前言

eTS发布有段时间了,用它写UI不光是代码易读性,还是代码量都是相当优秀。用过以后发现再也不想用java写UI了。前段时间尝试调试了碰一碰配网,使用的是碰一碰(个人体验版)的。正式版的需要企业账号才可以,使用的是java+js。今天来尝试下eTS开发,但是ArkUI只有在API7上才能支持,目前绝大多数手机还都是API6,所以配网部分只能先代码模拟测试,界面效果如下图:

用ArkUI实现碰一碰配网、设备控制-鸿蒙HarmonyOS技术社区用ArkUI实现碰一碰配网、设备控制-鸿蒙HarmonyOS技术社区

项目分为两个模块,碰一碰配网entry模块,设备控制control模块。不多说了上代码。

用ArkUI实现碰一碰配网、设备控制-鸿蒙HarmonyOS技术社区

entry模块

这个模块主要是实现设备联网。界面很简单。

UI界面

配网界面就是3个组件,一个图片2个text。

  1. build() { 
  2.   Row(){ 
  3.     Column() { 
  4.       Image($r('app.media.test')) 
  5.         .width(152) 
  6.         .height(152) 
  7.         .margin({ top: 16 }) 
  8.       Text(this.desc
  9.         .fontSize(14) 
  10.         .fontColor('#FF0000000'
  11.         .margin({ top: 16 }) 
  12.       Text(this.progress) 
  13.         .fontSize(14) 
  14.         .fontColor('#999999'
  15.         .margin({ top: 2,right: 24,bottom: 20,left: 24 }) 
  16.     } 
  17.     .height('35%'
  18.     .width('80%'
  19.     .margin('10%'
  20.     .borderRadius(10) 
  21.     .backgroundColor(0xFFFFFF) 
  22.   } 
  23.   .width('100%'
  24.   .height('100%'
  25.   .alignItems(VerticalAlign.Bottom) //这是Row的参数 
  26.   .backgroundColor(0x000000) 

配网流程

整个配网的流程就是手机碰触NFC贴纸,获取Product ID,然后通过Product ID去云端获取用户意图。说白了就是告诉手机要打开哪个包名,哪个模块。关于如何在华为开发者门户设置用户意图可以看我之前的帖子。这里就是启动了entry模块。

接下来分析用eTS如何实现这个过程:

1.导入hilink包

在build.gradle中进行配置,底层的实现都是通过调用API,并不需要自己写。

  1. dependencies { 
  2.     ... ... 
  3.     implementation(group'com.huawei.hilink'name'ailifeability', version: '1.0.0.1', ext: 'har'

2.调用PA能力。

使用JSCallJava调用API接口,这个可以参考OneHop模板,来实现一个default/common/fa-netconfig.ets它的作用就是将JAVA API转换为eTS函数接口,主要用到的就是FeatureAbility.callAbility(action)。

  1. function callAbilityFunc(callCode, argsObj, callbackFunc) { 
  2.   let action = {                        // 要调用java的信息存放在action 
  3.     bundleName : CONSTANT.BUNDLE_NAME, 
  4.     abilityName : CONSTANT.ABILITY_NAME, 
  5.     messageCode : callCode,             // callCode用来区分要调用哪一个API 
  6.     abilityType : 1, 
  7.     data : argsObj, 
  8.   }; 
  9.   return FeatureAbility.callAbility(action);//调用PA能力 

3.eTS生命周期回调函数

要在entry被拉起时自动执行配网,就要使用.eTS生命周期回调函数。

由于本篇主题是ArkUI,至于配网流程等专门写一篇帖子再来分析。

  1. aboutToAppear(){ 
  2.   this.discoverDevice() // 执行配网流程 

control模块

接下来和大家分享下在制作control模块时,学习到的ArkUI知识点和踩到的一些坑。其中部分内容官方文档也没有写,都是参考示例代码连蒙带猜。

1.设置窗口模式

在OneHop官方模板src/main/java/com/liangzili/myonehop/MainAbility.java下给window_modal设置了一个参数。在官方文档中好像没有关于这个参数的说明,也或许是我没有找到。

  1. public void onStart(Intent intent) { 
  2.     intent.setParam("window_modal", 3); 
  3.     ... ... 

测试发现这个参数可以很方便的实现类似弹窗下拉这样的效果,省去了很多界面代码。其中("window_modal", 3)就是配网entry页面的效果,("window_modal", 1)的效果可以看下图。而且比较有意思的是有1有3,但是传递2好像没啥效果。不过可惜的是,JS范式下传递这个参数效果如下图,但eTS下会有bug,要不就是弹窗无法拖拽,要不就是全屏无法设置大小。

2.app在线设计

在官方指导中有提到HiLink可以使用在线可视化的方式设置界面,效果如下图。

用ArkUI实现碰一碰配网、设备控制-鸿蒙HarmonyOS技术社区

看着就很方便,在线设计完成之后会得到一个界面文件。类似下图这样的效果。界面的数据要统一放到了src/main/resources/rawfile下,根据productName参数进行区选择,格式为JSON。(PS:本想体验下这个app在线设计,但是打开没有内容,我只好使用的模板里带的FAN_zh.json)

用ArkUI实现碰一碰配网、设备控制-鸿蒙HarmonyOS技术社区

control模块需要解析json文件的数据来绘制界面。

3.配置文件的解析

配置文件的解析也是java来完成的,所以我直接原文复制的OneHop模板的java代码,eTS部分,在src/main/ets/default/pages/index.ets下。

  1. async onPageShow(){ 
  2.   utils.setActionParam('com.liangzili.myonehop',  // 为action初始化参数 
  3.     'com.liangzili.myonehop.DataHandlerAbility', ABILITY_TYPE_INTERNAL) 
  4.   await this.requestTemplate() 
  5. .. ... 
  6.  async requestTemplate() { 
  7.   let action = utils.makeAction(ACTION_MESSAGE_CODE_GET_TEMPLATE, {}); 
  8.   let result = await FeatureAbility.callAbility(action); // 同样的方法去调用PA的能力 
  9.  
  10.   let resultJson = JSON.parse(result);  // 返回的结果保存在 result 中 
  11.   if (resultJson.code == 0) {               // 不等于0就调用失败了,可以通过失败码查找问题 
  12.     let template = JSON.parse(resultJson.data); 
  13.     this.parseJson(template.template); 
  14.   } 
  15. async parseJson(deviceInfo) { ... ... } // 最后就是解析JSON来生成界面了 

4.生成界面

其实如果用eTS范式单纯生成一个右侧这样的界面,可能只需要几十行代码。但是要解析在线生成的JSON界面文件,再兼容各种样式的控制界面来绘制UI,这个问题就会变得复杂的多。可能官方的意思是想通过在线设计降低程序的工作量,或者是为了统一UI风格,降低用户学习成本。

用ArkUI实现碰一碰配网、设备控制-鸿蒙HarmonyOS技术社区

index.ets

主界面分为两个区域,DeviceInfo() 和 Control(),DeviceInfo就一个主图和名字。

  1. build() { 
  2.   Stack({ alignContent: Alignment.Bottom }){        // 用来模拟一个上边圆角的效果 
  3.     Column(){}.height(35).width('100%').backgroundColor(0xF6F6F6) // 用来覆盖下端边框圆角 
  4.     Column() { 
  5.       DeviceInfo()  // 设备信息组件 
  6.       Control()     // 控制面板组件 
  7.     } 
  8.     .height('95%'
  9.     .width('100%'
  10.     .borderRadius(25) 
  11.     .backgroundColor(0xF6F6F6) 
  12.   } 
  13.   .width('100%'
  14.   .height('100%'
  15.   .backgroundColor(0x000000) 

Control.ets

界面中通过传递参数,来实现用一个组件,显示不同内容。

  1. build(){ 
  2.     Column(){ 
  3.       Reversal(this.reversalData1)                //开关组件 
  4.       Enum({ enumDatas: this.enumDatas1 })        //枚举组件 
  5.       Enum({ enumDatas: this.enumDatas2 })        //枚举组件 
  6.       Reversal(this.reversalData2)                //开关组件 
  7.     } 
  8.   } 

5.参数传递

组件间传值是我遇到问题比较大的地方,我总结了以下几种情况。这些基本能解决大部分的传值问题了。

1.单个变量

  1. // 调用端 
  2. Component1({a01:"a01"})     // 调用的时候参数用{}包裹 
  3.  
  4. // 被调用端 
  5. @Component 
  6. export struct Component1{ 
  7.   private a01:string      // 这里定义变量,用来接收 
  8.   build(){ 
  9.     Text(this.a01).fontSize(50) 
  10.   } 

2.对象键值对

  1. // 调用端 
  2. struct Index { 
  3.   parameter:{} = {b01: "b01",b02: "b02",} 
  4.   build() { 
  5.     Column(){ 
  6.       Component2(this.parameter)    // 调用的时候参数不用{}包裹 
  7.     } 
  8.   } 
  9.  
  10. // 被调用端 
  11. @Component 
  12. export struct Component2{ 
  13.   private b01:string      // 这里定义变量,用来接收 
  14.   private b02:string 
  15.   build(){ 
  16.     Column(){ 
  17.       Text(this.b01).fontSize(50) 
  18.       Text(this.b02).fontSize(50) 
  19.     } 
  20.   } 

3.对象数组

  1. // 调用端 
  2. struct Index { 
  3.   parameters:any[] = [ 
  4.     { 
  5.       c01:"c01"
  6.       c02:"c02" 
  7.     }, 
  8.     { 
  9.       c01:"c11"
  10.       c02:"c22" 
  11.     } 
  12.   ] 
  13.   build() { 
  14.     Column(){ 
  15.       Component3({ parameters: this.parameters })   // 传递参数是parameters,对象数组类型 
  16.     } 
  17.   } 
  18. // 被调用端 
  19. @Component 
  20. export struct Component3{ 
  21.   private parameters:any[]  // 定义同样的参数,同样的类型 
  22.   build(){ 
  23.     Column(){ 
  24.       ForEach(this.parameters,(item:any) => {   //【重要:获取数组之后可以直接使用ForEach遍历数据】 
  25.         Text(item.c01).fontSize(50) 
  26.         Text(item.c02).fontSize(50) 
  27.       },(item:any) => item.toString() // 文档说选填,但不填会失败 
  28.       ) 
  29.  
  30.     } 
  31.   } 

4.自定义类数组

  1. // 类 
  2. class enumData { 
  3.   image: Resource 
  4.   text: string 
  5.  
  6.   constructor(image: Resource, text: string) { 
  7.     this.image = image; 
  8.     this.text = text; 
  9.   } 
  10. // 调用端 
  11. @Entry 
  12. @Component 
  13. struct Index { 
  14.   enumDatas:enumData[] = this.getenumDatas() 
  15.   getenumDatas(){ 
  16.     let enumDatas: Array<enumData> = [] 
  17.     enumDatas.push(new enumData($r("app.media.icon"), "001")) 
  18.     enumDatas.push(new enumData($r("app.media.icon"), "002")) 
  19.     return enumDatas; 
  20.   } 
  21.  
  22.   build() { 
  23.     Column(){ 
  24.       Component4({ enumDatas: this.enumDatas }) 
  25.     } 
  26.   } 
  27. // 被调用端 
  28. @Component 
  29. export struct Component4{ 
  30.   private enumDatas:enumData[]  // 这里定义变量,用来接收 
  31.   build(){ 
  32.     Column(){ 
  33.       ForEach(this.enumDatas,(item:any) => { 
  34.         Image(item.image).width(50).height(50) 
  35.         Text(item.text).fontSize(50) 
  36.       },(item:any) => item.text.toString() // 文档说选填,但不填会失败 
  37.       ) 
  38.     } 
  39.   } 

6.发送设备控制信息

由于目前没有API7的真机进行调试,所以发送控制设备信息这部分还没有实现。但是以防万一控制流程先记录下来,方便以后再来添加。

与entry模块类似,需要在build.gradle中进行配置,同样的API。

  1. dependencies { 
  2.     ... ... 
  3.     implementation(group'com.huawei.hilink'name'ailifeability', version: '1.0.0.1', ext: 'har'

 eTS侧要实现这样的函数,来调用PA的能力。

  1. async setKeyValue(key, value) { 
  2.     let data = {}; 
  3.     data[key] = value; 
  4.     let action = utils.makeAction(ACTION_MESSAGE_CODE_DATACHANGED, data); 
  5.     let that = this; 
  6.     that.data.timer = setTimeout(function () { 
  7.         that.notifyObservers('showMessage', { 
  8.             'show'true 
  9.         }); 
  10.     }, WAIT_TIME); 
  11.     await FeatureAbility.callAbility(action); 

 src/main/java/com/liangzili/myonehop/DataHandlerAbility.java

java侧根据ACTION_MESSAGE_CODE_DATA_CHANGED来确定要调用的方法。

  1. case ACTION_MESSAGE_CODE_DATA_CHANGED: { 
  2.     String zsonStr = data.readString(); 
  3.     ZSONObject zsonObj = ZSONObject.stringToZSON(zsonStr); 
  4.     for (Map.Entry<String, Object> entry : zsonObj.entrySet()) { 
  5.         deviceDataHandler.modifyDeviceProperty(entry.getKey(), entry.getValue()); 
  6.     } 
  7.     break; 

以上就是我在使用ArkUI开发时,一些重要知识点的总结,希望对朋友们有所帮助。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-05-19 15:47:24

碰一碰连接设备开发鸿蒙

2022-12-23 20:46:37

遥控器应用鸿蒙

2022-05-17 10:33:58

设备开发鸿蒙操作系统

2022-01-17 14:51:20

鸿蒙HarmonyOS应用

2021-07-15 09:39:06

鸿蒙HarmonyOS应用

2021-02-23 19:24:51

数字人民币碰一碰支付

2023-02-03 16:31:33

2022-05-12 14:22:39

NFC标签鸿蒙

2021-03-20 22:11:16

数字人民币数字货币区块链

2021-04-27 13:58:03

数字人民币数字货币区块链

2022-10-25 14:51:11

设备开发鸿蒙

2020-05-06 17:08:40

缓存Key集群

2022-05-18 16:17:31

设备开发鸿蒙

2022-03-23 15:17:00

Harmony鸿蒙操作系统

2015-05-18 10:53:33

点赞
收藏

51CTO技术栈公众号