HarmonyOS JS FA 调用 Java PA 机制

开发 后端 OpenHarmony
本项目使用模拟文件下载进度变化的功能来给你展示JS FA订阅JAVA PA的能力,订阅之后JS可以一直实时获取到JAVA返回的进度数据来更新JS界面的进度条。

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

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

https://harmonyos.51cto.com

实现效果

一、项目介绍

本项目使用模拟文件下载进度变化的功能来给你展示JS FA订阅JAVA PA的能力,订阅之后JS可以一直实时获取到JAVA返回的进度数据来更新JS界面的进度条。另外,文件模拟下载完成跳转到一个求积的页面,在这个页面输入两个数,点击求积按钮会给你展示JS FA调用JAVA PA的能力,此处并不像订阅一样可以一直获取到java返回的数据,采用的模式是调用一次返回一次数据。

通过本项目,是想让你了解如下知识点:

​ 1) FeatureAbility.callAbility(OBJECT):调用PA能力。

​ 2) FeatureAbility.subscribeAbilityEvent(OBJECT, Function):订阅PA能力。

​ 3) FeatureAbility.unsubscribeAbilityEvent(OBJECT):取消订阅PA能力。

二、代码结构解读

HarmonyOS JS FA 调用 JAVA PA 机制-鸿蒙HarmonyOS技术社区

1、java/ServiceAbility : java与js的通信代码;

2、java-RequestParam :请求参数的实体类;

3、js-pages-index.hml : js模拟文件下载页;

4、js-pages-index.js : js订阅java pa代码;

5、js-calculate-calculate.hml : js求积页面;

6、js-calculate-calculate.js : 调用java pa代码;

7、config.json : js、java的配置文件,里面包括页面配置、service配置、窗体配置等等。

三、新建js project

右击—new—new project 。

HarmonyOS JS FA 调用 JAVA PA 机制-鸿蒙HarmonyOS技术社区

选择模板—next。

HarmonyOS JS FA 调用 JAVA PA 机制-鸿蒙HarmonyOS技术社区

输入项目名称、选择项目类型(单选)、api版本,设备类型,点击finish即可。

HarmonyOS JS FA 调用 JAVA PA 机制-鸿蒙HarmonyOS技术社区

四、订阅PA解读

点击下载按钮,向java端发送订阅请求。

  1. /** 
  2.  * 请求开启订阅模式 
  3.  */ 
  4. subscribe: async function() { 
  5.     this.isShow = true; // 显示进度条内容 
  6.     var that = this; 
  7.  
  8.     var actionData = {}; 
  9.     actionData.firstNum = that.message; 
  10.  
  11.     var action = {}; 
  12.     action.bundleName = 'com.example.javajscommunication'; // Ability的包名称,需要与PA端匹配,区分大小写 
  13.     action.abilityName = 'com.example.javajscommunication.ServiceAbility'; // Ability名称,需要与PA端匹配,区分大小写 
  14.     action.messageCode = ACTION_MESSAGE_CODE_PLUS_SUB; // Ability操作码(操作码定义PA的业务功能,需要与PA端约定) 
  15.     action.data = actionData; // 发送到Ability的数据,数据字段名称需要与PA端约定 
  16.     action.abilityType = ABILITY_TYPE_EXTERNAL; // Ability类型,对应PA端不同的实现方式 
  17.     action.syncOption = ACTION_SYNC; // PA侧请求消息处理同步/异步选项 0:同步方式,默认方式。 1:异步方式 
  18.  
  19.     await FeatureAbility.subscribeAbilityEvent(actionfunction (callbackData) { 
  20.         var callbackJson = JSON.parse(callbackData); // json字符串反序列化 
  21.         that.message = callbackJson.data.abilityEvent; 
  22.         if (that.message == 100) { // message 为100时进行跳转计算页面 
  23.             router.push({ 
  24.                 uri: "pages/calculate/calculate" 
  25.             }) 
  26.             that.unsubscribe(); // 取消订阅 
  27.             that.isShow = false; // 隐藏进度条 
  28.         } 
  29.     }) 

java端在ServiceAbility中对订阅请求进行处理,在内部类MyRemote的onRemoteRequest方法中根据code参数来判断请求类型进行相应处理。

  1. case ACTION_MESSAGE_CODE_PLUS_SUB: { 
  2.     go = true; // 开启可以下载状态 
  3.     remoteObjectHandler = data.readRemoteObject(); // 获取请求参数对象 
  4.     String zsonStr = data.readString(); // 获取参数字符串 
  5.  
  6.     try { 
  7.         param = ZSONObject.stringToClass(zsonStr, RequestParam.class); // 字符串对象转成RequestParam实例 
  8.     } catch (RuntimeException e) { 
  9.  
  10.     } 
  11.     startNotify(param); // 给js端发送信息 
  12.  
  13.     Map<String, Object> zsonResult = new HashMap<String, Object>();// 返回结果,关键字段应与Js方协商 
  14.     zsonResult.put("code", SUCCESS); 
  15.     reply.writeString(ZSONObject.toZSONString(zsonResult)); // map 对象转成json字符串,并返回给js端 
  16.     return true

 java端开启线程,按照5*3 每15毫秒的频率返回数据给js端。这里java发送给js的数据,js端会通过订阅java pa的回调函数中而实时获取到。

  1. /** 
  2.  *  开启线程,按照5*3 每15毫秒的频率返回数据给js端。这里java发送给js的数据, 
  3.  *  js端会通过订阅java pa的回调函数中而实时获取到 
  4.  */ 
  5. public void startNotify(RequestParam param) { 
  6.     number = param.getFirstNum(); // 获取当前进度值从请求中获取 
  7.     new Thread(() -> { // 开启线程 
  8.         while (go) { 
  9.             try { 
  10.                 Thread.sleep(5 * 3); // 线程睡眠15毫秒后继续往下执行 
  11.                 MessageParcel data = MessageParcel.obtain(); // 创建索引为0的空MessageParcel对象 
  12.                 MessageParcel reply = MessageParcel.obtain(); 
  13.                 zsonEvent.put("abilityEvent", number++); 
  14.                 if (number == 101) { // number超过100 go状态设为false 下载结束 
  15.                     go = false
  16.                 } 
  17.                 data.writeString(ZSONObject.toZSONString(zsonEvent)); // 数据存到MessageParcel载体 
  18.                 remoteObjectHandler.sendRequest(100, data, reply, option); // 发送 
  19.                 reply.reclaim(); // 回收 
  20.                 data.reclaim(); 
  21.             } catch (RemoteException | InterruptedException e) { 
  22.                 break; 
  23.             } 
  24.         } 
  25.     }).start(); 

js页面点击取消按钮,取消订阅模式, java端停止返回数据。

js端代码如下:

  1. /** 
  2.  * 请求取消订阅, java端停止返回数据 
  3.  */ 
  4. unsubscribe: async function() { 
  5.     var action = {}; 
  6.     action.bundleName = 'com.example.javajscommunication'; // Ability的包名称,需要与PA端匹配,区分大小写 
  7.     action.abilityName = 'com.example.javajscommunication.ServiceAbility'; // Ability名称,需要与PA端匹配,区分大小写 
  8.     action.messageCode = ACTION_MESSAGE_CODE_PLUS_UNSUB; // Ability操作码(操作码定义PA的业务功能,需要与PA端约定) 
  9.     action.abilityType = ABILITY_TYPE_EXTERNAL; // Ability类型,对应PA端不同的实现方式 
  10.     action.syncOption = ACTION_SYNC;  // PA侧请求消息处理同步/异步选项 0:同步方式,默认方式。 1:异步方式 
  11.  
  12.     var result = await FeatureAbility.unsubscribeAbilityEvent(action); // 取消订阅 
  13.     var ret = JSON.parse(result); // 反序列化, 
  14.     if (ret.code == 0) { 
  15.         prompt.showToast({ 
  16.             message: '取消下载成功' 
  17.         }) 
  18.     } else { 
  19.         prompt.showToast({ 
  20.             message: '取消下载失败' 
  21.         }) 
  22.     } 

 java端service代码如下:

  1. case ACTION_MESSAGE_CODE_PLUS_UNSUB: { 
  2.     go = false; // 停止方法startNotify中的while循环,停止往js端发送消息 
  3.     Map<String, Object> zsonResult = new HashMap<String, Object>(); 
  4.     zsonResult.put("code", SUCCESS); 
  5.     reply.writeString(ZSONObject.toZSONString(zsonResult)); // 响应js端 
  6.     return true

五、调用PA解读

获取input输入的值,作为js端传递过去的值。

  1. /**  
  2.   * 取传过去的第一个值  
  3.   */ 
  4.     numOne (e){ 
  5.         this.numOne = e.value 
  6.     },   
  7.  /**  
  8.   * 获取传过去的第二个值 
  9.   */ 
  10.     numTwo (e){ 
  11.         this.numTwo = e.value 
  12.     } 

 点击求积按钮 发送调用模式的请求。

  1. calculate: async function() { 
  2.     var actionData = {}; // key值对应PA端的RequestParam类的成员字段 
  3.     actionData.firstNum = this.numOne; 
  4.     actionData.secondNum = this.numTwo; 
  5.  
  6.     var action = {}; 
  7.     action.bundleName = 'com.example.javajscommunication'; // Ability的包名称,需要与PA端匹配,区分大小写 
  8.     action.abilityName = 'com.example.javajscommunication.ServiceAbility'; // Ability名称,需要与PA端匹配,区分大小写 
  9.     action.messageCode = ACTION_MESSAGE_CODE_PLUS; // Ability操作码(操作码定义PA的业务功能,需要与PA端约定) 
  10.     action.data = actionData; // 发送到Ability的数据,数据字段名称需要与PA端约定 
  11.     action.abilityType = ABILITY_TYPE_EXTERNAL; // Ability类型,对应PA端不同的实现方式 
  12.     action.syncOption = ACTION_SYNC;  // PA侧请求消息处理同步/异步选项 0:同步方式,默认方式。 1:异步方式 
  13.  
  14.     var result = await FeatureAbility.callAbility(action); 
  15.     var ret = JSON.parse(result); 
  16.     if (ret.code == 0) { 
  17.         this.message =  'java端传回的数据为:' + JSON.stringify(ret.abilityResult); 
  18.     } else { 
  19.         this.message =  'java端传回的数据报错' + JSON.stringify(ret.code); 
  20.     } 
  21. }, 

java端在ServiceAbility中对订阅请求进行处理,在内部类MyRemote的onRemoteRequest方法中根据code参数来判断请求类型进行相应处理。这里java发送给js的数据,js端会通过调用java pa的结果而获取到。

  1. case ACTION_MESSAGE_CODE_PLUS: { 
  2.     String zsonStr = data.readString(); // 获取传入参数的字符串 
  3.     RequestParam param = new RequestParam(); 
  4.     try { 
  5.         param = ZSONObject.stringToClass(zsonStr, RequestParam.class); // 字符串对象转成RequestParam实例 
  6.     } catch (RuntimeException e) { 
  7.  
  8.     } 
  9.  
  10.     // 返回结果仅支持可序列化的Object类型 
  11.     Map<String, Object> zsonResult = new HashMap<>(); 
  12.     zsonResult.put("code", SUCCESS); 
  13.     zsonResult.put("abilityResult", param.getFirstNum() + " * " + param.getSecondNum() + " = " + (param.getFirstNum() * param.getSecondNum())); 
  14.     reply.writeString(ZSONObject.toZSONString(zsonResult)); // 数据返回给js端 
  15.     return true

 返回到前一个页面,这里在页面js中import router from ‘@system.router’,然后利用router对象的相关方法返回。

  1. back(){ 
  2.     router.back() // 返回到前一个页面 

六、代码参考

https://gitee.com/chinasoft6_ohos/java-js-communication

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

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

https://harmonyos.51cto.com

 

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

2021-10-27 10:05:55

鸿蒙HarmonyOS应用

2022-03-07 14:58:10

ArkUIJS FAJava

2021-12-20 10:07:39

鸿蒙HarmonyOS应用

2021-11-15 15:11:14

鸿蒙HarmonyOS应用

2022-06-02 14:27:05

UI框架JS

2021-07-16 09:54:49

鸿蒙HarmonyOS应用

2022-02-24 16:00:59

Ability鸿蒙JS

2022-02-17 21:28:08

AbilityJSFA鸿蒙

2022-02-17 21:19:35

JSFA操作系统鸿蒙

2022-05-24 15:06:57

AbilityeTS FA鸿蒙

2015-03-26 13:14:53

javascriptjs callback实现调用

2022-05-20 10:56:54

AbilityeTS FA调用

2021-06-24 14:41:16

鸿蒙HarmonyOS应用

2017-05-02 22:38:44

前端开发JS事件循环机制

2022-05-16 11:17:01

应用开发JSJAVA

2022-02-17 21:05:26

AbilityJS FAJava PA

2022-09-08 15:18:51

Ability鸿蒙

2021-03-02 09:29:29

鸿蒙HarmonyOS应用开发

2021-08-04 10:22:27

鸿蒙HarmonyOS应用

2015-11-20 11:20:54

js开发
点赞
收藏

51CTO技术栈公众号