HarmonyOS学习路之开发篇—Java UI框架(JS FA调用Java PA)

news/2025/3/12 12:18:35/

JS FA调用Java PA机制

使用兼容JS的类Web开发范式的方舟开发框架提供了JS FA(Feature Ability)调用Java PA(Particle Ability)的机制,该机制提供了一种通道来传递方法调用、处理数据返回以及订阅事件上。

当前提供Ability和Internal Ability两种调用方式。

  • Ability:拥有独立的Ability生命周期,FA使用远端进程通信拉起并请求PA服务,适用于基本服务供多FA调用或者服务在后台独立运行的场景。
  • Internal Ability:与FA共进程,采用内部函数调用的方式和FA进行通信,适用于对服务响应时延要求较高的场景。该方式下PA不支持其他FA访问调用。

    对于Internal Ability调用方式的开发,可以使用工具自动生成代码(自动生成下篇文章详解),提高开发效率。

JS端与Java端通过bundleName和abilityName来进行关联。在系统收到JS调用请求后,根据开发者在JS接口中设置的参数来选择对应的处理方式。开发者在onRemoteRequest()中实现PA提供的业务逻辑。

FA调用PA接口

FA端提供以下三个JS接口:

  • FeatureAbility.callAbility(OBJECT):调用PA能力。
  • FeatureAbility.subscribeAbilityEvent(OBJECT, Function):订阅PA能力。
  • FeatureAbility.unsubscribeAbilityEvent(OBJECT):取消订阅PA能力。

PA端提供以下两类接口:

  • IRemoteObject.onRemoteRequest(int, MessageParcel, MessageParcel, MessageOption):Ability调用方式,FA使用远端进程通信拉起并请求PA服务。
  • AceInternalAbility.AceInternalAbilityHandler.onRemoteRequest(int, MessageParcel, MessageParcel, MessageOption):Internal Ability调用方式,采用内部函数调用的方式和FA进行通信。

FA调用PA常见问题

  • callAbility返回报错:"Internal ability not register."

    返回该错误说明JS接口调用请求未在系统中找到对应的InternalAbilityHandler进行处理,因此需要检查以下几点是否正确执行:

    1. 在AceAbility继承类中对AceInternalAbility继承类执行了register方法,具体注册可参考Internal Ability的示例代码。
    2. JS侧填写的bundleName和abilityName与AceInternalAbility继承类构造函数中填写的名称保持相同,大小写敏感。
    3. 检查JS端填写的abilityType(0:Ability; 1:Internal Ability),确保没有将AbilityType缺省或误填写为Ability方式。

    Ability和Internal Ability是两种不同的FA调用PA的方式。

Ability和InternalAbility差异项

差异项

Ability

InternalAbility

JS端(abilityType)

0

1

是否需要在config.json的abilities中为PA添加声明

需要(有独立的生命周期)

不需要(和FA共生命周期)

是否需要在FA中注册

不需要

需要

继承的类

ohos.aafwk.ability.Ability

ohos.ace.ability.AceInternalAbility

是否允许被其他FA访问调用

  • FeatureAbility.callAbility中syncOption参数说明:
    • 对于JS FA侧,返回的结果都是Promise对象,因此无论该参数取何值,都采用异步方式等待PA侧响应。
    • 对于JAVA PA侧,在Internal Ability方式下收到FA的请求后,根据该参数的取值来选择:通过同步的方式获取结果后返回;或者异步执行PA逻辑,获取结果后使用remoteObject.sendRequest的方式将结果返回FA。
  • 使用await方式调用时IDE编译报错,需引入babel-runtime/regenerator。

示例参考

JS端调用FeatureAbility接口,传入两个Number参数,Java端接收后返回两个数的和。

JS FA应用的JS模块(entry/src/main)的典型开发目录结构如下:

  • FA JavaScript端

使用Internal Ability方式时,需要将对应的action.abilityType值改为ABILITY_TYPE_INTERNAL。

// abilityType: 0-Ability; 1-Internal Ability
const ABILITY_TYPE_EXTERNAL = 0;
const ABILITY_TYPE_INTERNAL = 1;
// syncOption(Optional, default sync): 0-Sync; 1-Async
const ACTION_SYNC = 0;
const ACTION_ASYNC = 1;
const ACTION_MESSAGE_CODE_PLUS = 1001;
export default {plus: async function() {var actionData = {};actionData.firstNum = 1024;actionData.secondNum = 2048;var action = {};action.bundleName = 'com.example.hiaceservice';action.abilityName = 'com.example.hiaceservice.ComputeServiceAbility';action.messageCode = ACTION_MESSAGE_CODE_PLUS;action.data = actionData;action.abilityType = ABILITY_TYPE_EXTERNAL;action.syncOption = ACTION_SYNC;var result = await FeatureAbility.callAbility(action);var ret = JSON.parse(result);if (ret.code == 0) {console.info('plus result is:' + JSON.stringify(ret.abilityResult));} else {console.error('plus error code:' + JSON.stringify(ret.code));}}
}
  • PA端(Ability方式)

功能代码实现:

在java目录下新建一个Service Ability,文件命名为ComputeServiceAbility.java

package com.example.hiaceservice;// ohos相关接口包
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.rpc.IRemoteBroker;
import ohos.rpc.IRemoteObject;
import ohos.rpc.RemoteObject;
import ohos.rpc.MessageParcel;
import ohos.rpc.MessageOption;
import ohos.utils.zson.ZSONObject;import java.util.HashMap;
import java.util.Map;public class ComputeServiceAbility extends Ability {// 定义日志标签private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "MY_TAG");private MyRemote remote = new MyRemote();// FA在请求PA服务时会调用Ability.connectAbility连接PA,连接成功后,需要在onConnect返回一个remote对象,供FA向PA发送消息@Overrideprotected IRemoteObject onConnect(Intent intent) {super.onConnect(intent);return remote.asObject();}class MyRemote extends RemoteObject implements IRemoteBroker {private static final int SUCCESS = 0;private static final int ERROR = 1;private static final int PLUS = 1001;   MyRemote() {super("MyService_MyRemote");}@Overridepublic boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {switch (code) {case PLUS: {String dataStr = data.readString();RequestParam param = new RequestParam();try {    param = ZSONObject.stringToClass(dataStr, RequestParam.class);} catch (RuntimeException e) {    HiLog.error(LABEL, "convert failed.");}// 返回结果当前仅支持String,对于复杂结构可以序列化为ZSON字符串上报Map<String, Object> result = new HashMap<String, Object>();result.put("code", SUCCESS);result.put("abilityResult", param.getFirstNum() + param.getSecondNum());reply.writeString(ZSONObject.toZSONString(result));break;}default: {Map<String, Object> result = new HashMap<String, Object>();result.put("abilityError", ERROR);reply.writeString(ZSONObject.toZSONString(result));return false;}}return true;}@Overridepublic IRemoteObject asObject() {return this;}}
}

请求参数代码:

RequestParam.java

public class RequestParam {private int firstNum;private int secondNum;public int getFirstNum() {return firstNum;}public void setFirstNum(int firstNum) {this.firstNum = firstNum;}public int getSecondNum() {return secondNum;}public void setSecondNum(int secondNum) {this.secondNum = secondNum;}
}

PA端(Internal Ability方式)

功能代码实现(以下代码可以使用工具自动生成):

在java目录下新建一个Service Ability,文件命名为ComputeInternalAbility.java

package com.example.hiaceservice;// ohos相关接口包
import ohos.ace.ability.AceInternalAbility;
import ohos.app.AbilityContext;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.rpc.IRemoteObject;
import ohos.rpc.MessageOption;
import ohos.rpc.MessageParcel;
import ohos.rpc.RemoteException;
import ohos.utils.zson.ZSONObject;import java.util.HashMap;
import java.util.Map;public class ComputeInternalAbility extends AceInternalAbility {private static final String BUNDLE_NAME = "com.example.hiaceservice";private static final String ABILITY_NAME = "com.example.hiaceservice.ComputeInternalAbility";private static final int SUCCESS = 0;private static final int ERROR = 1;private static final int PLUS = 1001;// 定义日志标签private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "MY_TAG");private static ComputeInternalAbility instance;private AbilityContext abilityContext;// 如果多个Ability实例都需要注册当前InternalAbility实例,需要更改构造函数,设定自己的bundleName和abilityNamepublic ComputeInternalAbility() {super(BUNDLE_NAME, ABILITY_NAME);}public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {switch (code) {case PLUS: {String dataStr = data.readString();RequestParam param = new RequestParam();try {    param = ZSONObject.stringToClass(dataStr, RequestParam.class);} catch (RuntimeException e) {    HiLog.error(LABEL, "convert failed.");}// 返回结果当前仅支持String,对于复杂结构可以序列化为ZSON字符串上报Map<String, Object> result = new HashMap<String, Object>();result.put("code", SUCCESS);result.put("abilityResult", param.getFirstNum() + param.getSecondNum());// SYNCif (option.getFlags() == MessageOption.TF_SYNC) {reply.writeString(ZSONObject.toZSONString(result));} else {// ASYNCMessageParcel responseData = MessageParcel.obtain();responseData.writeString(ZSONObject.toZSONString(result));IRemoteObject remoteReply = reply.readRemoteObject();try {remoteReply.sendRequest(0, responseData, MessageParcel.obtain(), new MessageOption());} catch (RemoteException exception) {return false;} finally {responseData.reclaim();}}break;}default: {Map<String, Object> result = new HashMap<String, Object>();result.put("abilityError", ERROR);reply.writeString(ZSONObject.toZSONString(result));return false;}}return true;}/*** Internal ability 注册接口。*/public static void register(AbilityContext abilityContext) {instance = new ComputeInternalAbility();instance.onRegister(abilityContext);}private void onRegister(AbilityContext abilityContext) {this.abilityContext = abilityContext;this.setInternalAbilityHandler((code, data, reply, option) -> {return this.onRemoteRequest(code, data, reply, option);});}/*** Internal ability 注销接口。*/public static void unregister() {instance.onUnregister();}private void onUnregister() {abilityContext = null;this.setInternalAbilityHandler(null);}
}

Internal Ability注册:修改继承AceAbility工程中的代码

public class MainAbility extends AceAbility {@Overridepublic void onStart(Intent intent) {// 注册, 如果需要在Page初始化(onInit或之前)时调用AceInternalAbility的能力,注册操作需要在super.onStart之前进行ComputeInternalAbility.register(this);...super.onStart(intent);}@Override public void onStop() {// 注销ComputeInternalAbility.unregister();     super.onStop();}
}


http://www.ppmy.cn/news/419912.html

相关文章

Honor V10 BKL-AL20 ROOT(Magisk方式)

背景:因为下周有Android课程,就想着上课前刷个机(虽然并没有什么关系) 前期提示:刷机于 20180905,本文于 20180906于刷机第二天发布此文,使用测试中本文仅做过程复述,并非作为教程发布,如有问题,后果自负内容仅供参考,因各种原因复做结果不一定一致全过程采用线刷强…

实测荣耀V20:7折的价格,华为Mate 20一样的AI体验

乾明 发自 凹非寺 量子位 报道 | 公众号 QbitAI 虽然相对更便宜&#xff0c;但体验一点都不差。 这是量子位先后测评了华为Mate 20 Pro和荣耀V20的之后的第一感觉。 2018年年末&#xff0c;华为家的小儿子荣耀V20“出生”了。 芯片配备双NPU麒麟980&#xff0c;并没有受到“歧视…

华为Atlas人工智能计算平台概述

人工智能的四大要素&#xff1a;数据、算力、算法、场景 AI芯片&#xff1a;也被称为AI加速器&#xff0c;即专门用于处理人工智能应用中的大量计算任务的功能模块。 AI芯片分类 从技术架构来看&#xff0c;大致分为四个类型&#xff1a;CPU、GPU、ASIC、FPGA。之前的博客中…

华为荣耀手机 (HUAWEI Honor V9) USB 调试 - ADB 调试

华为荣耀手机 (HUAWEI Honor V9) USB 调试 - ADB 调试 1. 开发者模式 Settings (设置) -> System (系统) -> About phone (关于手机) -> Build number (版本号) 连续点击 Build number (版本号) 7 次进入 开发者模式。 You are already a developer! 您正处于开发者模…

无需twrp实现magisk刷入(以华为荣耀v9为例)

shebTOC 前期准备 设备环境&#xff1a;华为荣耀v9&#xff08;DUK-AL20&#xff09;&#xff0c;EMUI 9.1.0.230&#xff08;COOE229R1P11&#xff09;GPU Turbo&#xff08;设备已解锁&#xff09; 从官方ROM包中提取了recovery_ramdisk.img备用&#xff0c;电脑与手机能ad…

QML TreeView 简单使用

本文主要介绍 QML 中 TreeView 的基本使用方法&#xff0c;包括&#xff1a;TreeView的适用场景&#xff1b; 控件简介 QML TreeView 是 Qt Quick 中的一个组件&#xff0c;用于显示树形结构的数据。它提供了一种以层次结构方式展示数据的方式&#xff0c;其中每个节点可以包含…

软件 安全,处理威胁STRIDE模型

微软威胁分析工具&#xff1a; https://www.microsoft.com/en-us/securityengineering/sdl/threatmodeling?azure-portaltrue STRIDE 是微软定义的6中威胁 身份假冒&#xff08;Spoofing&#xff09; 身份假冒&#xff0c;即伪装成某对象或某人。例如&#xff0c;我们通过伪…

什么是HMI和SCADA?两者有什么区别

前言 几十年来&#xff0c;工业控制系统在工业自动化中发挥了重要作用&#xff0c;它允许过程制造商从生产车间采集、分析、处理数据。 在当今瞬息万变的工业环境中&#xff0c;制造商和公用事业公司必须采用现代HMI/SCADA和数字化转型&#xff0c;以跟上变化的步伐&#xff0…