HarmonyOS JS FA 调用 JAVA PA 机制 原创 精华

中软HOS小鸿
发布于 2021-9-1 16:50
浏览
7收藏

实现效果

HarmonyOS JS FA 调用 JAVA PA 机制-鸿蒙开发者社区

一、项目介绍

    本项目使用模拟文件下载进度变化的功能来给你展示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 机制-鸿蒙开发者社区
    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

  1. 右击—new—new project 。
    HarmonyOS JS FA 调用 JAVA PA 机制-鸿蒙开发者社区

  2. 选择模板—next。
    HarmonyOS JS FA 调用 JAVA PA 机制-鸿蒙开发者社区

  3. 输入项目名称、选择项目类型(单选)、api版本,设备类型,点击finish即可。
    HarmonyOS JS FA 调用 JAVA PA 机制-鸿蒙开发者社区

四、订阅PA解读

  1. 点击下载按钮,向java端发送订阅请求。
/**
 * 请求开启订阅模式
 */
subscribe: async function() {
    this.isShow = true; // 显示进度条内容
    var that = this;

    var actionData = {};
    actionData.firstNum = that.message;

    var action = {};
    action.bundleName = 'com.example.javajscommunication'; // Ability的包名称,需要与PA端匹配,区分大小写
    action.abilityName = 'com.example.javajscommunication.ServiceAbility'; // Ability名称,需要与PA端匹配,区分大小写
    action.messageCode = ACTION_MESSAGE_CODE_PLUS_SUB; // Ability操作码(操作码定义PA的业务功能,需要与PA端约定)
    action.data = actionData; // 发送到Ability的数据,数据字段名称需要与PA端约定
    action.abilityType = ABILITY_TYPE_EXTERNAL; // Ability类型,对应PA端不同的实现方式
    action.syncOption = ACTION_SYNC; // PA侧请求消息处理同步/异步选项 0:同步方式,默认方式。 1:异步方式

    await FeatureAbility.subscribeAbilityEvent(action, function (callbackData) {
        var callbackJson = JSON.parse(callbackData); // json字符串反序列化
        that.message = callbackJson.data.abilityEvent;
        if (that.message == 100) { // message 为100时进行跳转计算页面
            router.push({
                uri: "pages/calculate/calculate"
            })
            that.unsubscribe(); // 取消订阅
            that.isShow = false; // 隐藏进度条
        }
    })
}
  1. java端在ServiceAbility中对订阅请求进行处理,在内部类MyRemote的onRemoteRequest方法中根据code参数来判断请求类型进行相应处理。
case ACTION_MESSAGE_CODE_PLUS_SUB: {
    go = true; // 开启可以下载状态
    remoteObjectHandler = data.readRemoteObject(); // 获取请求参数对象
    String zsonStr = data.readString(); // 获取参数字符串

    try {
        param = ZSONObject.stringToClass(zsonStr, RequestParam.class); // 字符串对象转成RequestParam实例
    } catch (RuntimeException e) {

    }
    startNotify(param); // 给js端发送信息

    Map<String, Object> zsonResult = new HashMap<String, Object>();// 返回结果,关键字段应与Js方协商
    zsonResult.put("code", SUCCESS);
    reply.writeString(ZSONObject.toZSONString(zsonResult)); // map 对象转成json字符串,并返回给js端
    return true;
}
  1. java端开启线程,按照5*3 每15毫秒的频率返回数据给js端。这里java发送给js的数据,js端会通过订阅java pa的回调函数中而实时获取到。
/**
 *  开启线程,按照5*3 每15毫秒的频率返回数据给js端。这里java发送给js的数据,
 *  js端会通过订阅java pa的回调函数中而实时获取到
 */
public void startNotify(RequestParam param) {
    number = param.getFirstNum(); // 获取当前进度值从请求中获取
    new Thread(() -> { // 开启线程
        while (go) {
            try {
                Thread.sleep(5 * 3); // 线程睡眠15毫秒后继续往下执行
                MessageParcel data = MessageParcel.obtain(); // 创建索引为0的空MessageParcel对象
                MessageParcel reply = MessageParcel.obtain();
                zsonEvent.put("abilityEvent", number++);
                if (number == 101) { // number超过100 go状态设为false 下载结束
                    go = false;
                }
                data.writeString(ZSONObject.toZSONString(zsonEvent)); // 数据存到MessageParcel载体
                remoteObjectHandler.sendRequest(100, data, reply, option); // 发送
                reply.reclaim(); // 回收
                data.reclaim();
            } catch (RemoteException | InterruptedException e) {
                break;
            }
        }
    }).start();
}
  1. js页面点击取消按钮,取消订阅模式, java端停止返回数据。

js端代码如下:

/**
 * 请求取消订阅, java端停止返回数据
 */
unsubscribe: async function() {
    var action = {};
    action.bundleName = 'com.example.javajscommunication'; // Ability的包名称,需要与PA端匹配,区分大小写
    action.abilityName = 'com.example.javajscommunication.ServiceAbility'; // Ability名称,需要与PA端匹配,区分大小写
    action.messageCode = ACTION_MESSAGE_CODE_PLUS_UNSUB; // Ability操作码(操作码定义PA的业务功能,需要与PA端约定)
    action.abilityType = ABILITY_TYPE_EXTERNAL; // Ability类型,对应PA端不同的实现方式
    action.syncOption = ACTION_SYNC;  // PA侧请求消息处理同步/异步选项 0:同步方式,默认方式。 1:异步方式

    var result = await FeatureAbility.unsubscribeAbilityEvent(action); // 取消订阅
    var ret = JSON.parse(result); // 反序列化,
    if (ret.code == 0) {
        prompt.showToast({
            message: '取消下载成功'
        })
    } else {
        prompt.showToast({
            message: '取消下载失败'
        })
    }
}

java端service代码如下:

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

五、调用PA解读

  1. 获取input输入的值,作为js端传递过去的值。
 /** 
  * 取传过去的第一个值 
  */
    numOne (e){
        this.numOne = e.value
    },  
 /** 
  * 获取传过去的第二个值
  */
    numTwo (e){
        this.numTwo = e.value
    }
  1. 点击求积按钮 发送调用模式的请求。
calculate: async function() {
    var actionData = {}; // key值对应PA端的RequestParam类的成员字段
    actionData.firstNum = this.numOne;
    actionData.secondNum = this.numTwo;

    var action = {};
    action.bundleName = 'com.example.javajscommunication'; // Ability的包名称,需要与PA端匹配,区分大小写
    action.abilityName = 'com.example.javajscommunication.ServiceAbility'; // Ability名称,需要与PA端匹配,区分大小写
    action.messageCode = ACTION_MESSAGE_CODE_PLUS; // Ability操作码(操作码定义PA的业务功能,需要与PA端约定)
    action.data = actionData; // 发送到Ability的数据,数据字段名称需要与PA端约定
    action.abilityType = ABILITY_TYPE_EXTERNAL; // Ability类型,对应PA端不同的实现方式
    action.syncOption = ACTION_SYNC;  // PA侧请求消息处理同步/异步选项 0:同步方式,默认方式。 1:异步方式

    var result = await FeatureAbility.callAbility(action);
    var ret = JSON.parse(result);
    if (ret.code == 0) {
        this.message =  'java端传回的数据为:' + JSON.stringify(ret.abilityResult);
    } else {
        this.message =  'java端传回的数据报错' + JSON.stringify(ret.code);
    }
},
  1. java端在ServiceAbility中对订阅请求进行处理,在内部类MyRemote的onRemoteRequest方法中根据code参数来判断请求类型进行相应处理。这里java发送给js的数据,js端会通过调用java pa的结果而获取到。
case ACTION_MESSAGE_CODE_PLUS: {
    String zsonStr = data.readString(); // 获取传入参数的字符串
    RequestParam param = new RequestParam();
    try {
        param = ZSONObject.stringToClass(zsonStr, RequestParam.class); // 字符串对象转成RequestParam实例
    } catch (RuntimeException e) {

    }

    // 返回结果仅支持可序列化的Object类型
    Map<String, Object> zsonResult = new HashMap<>();
    zsonResult.put("code", SUCCESS);
    zsonResult.put("abilityResult", param.getFirstNum() + " * " + param.getSecondNum() + " = " + (param.getFirstNum() * param.getSecondNum()));
    reply.writeString(ZSONObject.toZSONString(zsonResult)); // 数据返回给js端
    return true;
}
  1. 返回到前一个页面,这里在页面js中import router from ‘@system.router’,然后利用router对象的相关方法返回。
back(){
    router.back() // 返回到前一个页面
}

六、代码参考

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

作者 :晋国晨

更多原创内容请关注:开鸿 HarmonyOS 学院

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,共建鸿蒙生态,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
已于2021-9-10 15:59:05修改
9
收藏 7
回复
举报
4条回复
按时间正序
/
按时间倒序
mb609898e2cfb86
mb609898e2cfb86

整个流程很完整,感谢分享。

回复
2021-9-1 18:22:39
火莹
火莹

整个流程很完整,感谢分享。

回复
2021-9-2 09:10:13
深开鸿
深开鸿

解释的很到位

回复
2021-9-2 09:32:39
修身养生
修身养生

感谢分享

回复
2021-9-26 16:31:05
回复
    相关推荐