鸿蒙JS FA调用PA 原创 精华
一、目标
实现通过JS FA调用PA的能力
二、效果
三、基础知识
3.1、什么是FA?什么是PA?
要说明FA和PA,首先需要了解:Ability是什么?
Ability是应用所具备能力的抽象,是系统调度应用的最小单元,也是应用程序的重要组成部分。一个应用可以具备多种能力(多个Ability),HarmonyOS支持应用以Ability为单位进行部署,Ability可以分为FA和PA。
FA:Feature Ability,带有界面,支持Page Ability,Page模板是FA唯一支持的模板,用于提供与用户交互的能力。一个Page实例可以包含一组相关的页面,每一个页面用一个AbilitySlice实例表示。
PA:Particle Ability,不带界面,支持Service Ability和Data Ability,其中Service模板用于提供后台运行任务的能力,Data模板用于对外部提供统一的数据访问能力。
3.2、远端调用Ability和本地调用Internal Ability两种调用方式有什么区别?
- Ability:拥有独立的Ability生命周期,FA使用远端进程通信拉起并请求PA服务,适用于基本服务供多FA调用或者服务在后台独立运行的场景。
- Internal Ability:与FA共进程,采用内部函数调用的方式和FA进行通信,适用于对服务响应时延要求较高的场景。该方式下PA不支持其他FA访问调用。
Ability和InternalAbility差异项
差异 | Ability | Internal Ability |
---|---|---|
JS端(abilityType) | 0 | 1 |
是否需要在config.json的abilities中为PA添加声明 | 需要(有独立的生命周期) | 不需要(与FA共生命周期) |
是否需要在FA中注册 | 不需要 | 需要 |
继承的类 | ohos.aafwk.ability.Ability | ohos.ace.ability.AceInternalAbility |
是否允许被其他FA访问调用 | 是 | 否 |
3.3、FA调PA机制介绍
该机制在HarmonyOS引擎内提供了一种通道来传递方法调用、数据返回、事件上报。具体描述:JS端与Java端通过接口扩展机制进行通信,通过bundleName和abilityName来进行关联。在FeatureAbility Plugin收到JS调用请求后,系统根据开发者在JS指定的abilityType,Ability或Internal Ability,来选择对应的方式进行处理。开发者在onRemoteRequest()中实现PA提供的业务逻辑,不同的业务通过业务码来区分。
3.4、官方文档
基于JS扩展的类Web开发范式的方舟开发框架提供JS FA调用Java PA的机制。
3.5、综合案例
四、JS FA调用Java PA实践
4.1、在实战之前先说明几个接口
4.1.1、FA提供的JS接口
接口 | 描述 | 备注 |
---|---|---|
FeatureAbility.callAbility(OBJECT) | JS FA 调用PA(Particle Ability)提供的能力 | SDK接口 |
FeatureAbility.subscribeAbilityEvent(OBJECT, Function) | 订阅PA能力 | SDK接口 |
FeatureAbility.unsubscribeAbilityEvent(OBJECT) | 取消订阅PA能力 | SDK接口 |
4.1.2、PA端提供以下接口
接口 | 描述 | 备注 |
---|---|---|
IRemoteObject.onRemoteRequest(int, MessageParcel, MessageParcel, MessageOption) | Ability调用方式,FA使用远端进程通信拉起并请求PA服务 | SDK接口 |
AceInternalAbility.AceInternalAbilityHandler.onRemoteRequest(int, MessageParcel, MessageParcel, MessageOption) | Internal Ability调用方式,采用内部函数调用的方式和FA进行通信 | SDK接口 |
4.2、实战
需求:在页面(JS FA)上输入两个数字,点击计算,通过Java PA进行计算后返回结果,将显示在屏幕上。
说明:本实战演示两个数的计算,如果说实现两个数的计算其实不需要这么复杂的逻辑,直接在JS层就可以完成,但本实战只是为了演示JS FA调用PA的能力,实现JS FA调用PA中的方法,也就是不同语音直接的接口调用,并将结果返回JS FA中显示,重点介绍Internal Ability实现方式。
4.2.1、创建项目
说明:通过DevEco Studio创建 JS 类型的项目
提醒:如果你是真机调试,建议在AGC(AppGallery Connect)平台上创建相关的项目和应用,这样在开发调试阶段,可以通过 Automatically generate signing 自动生成临时的认证和签名完成调试。官方介绍:使用真机调试
1、在AGC平台上创建项目和HarmonyOS 应用
2、在project的debug环境下通过Automatically generate signing 自动生成调试签名和认证
4.2.2、项目目录介绍
下面简单介绍下JS FA调用PA的项目目录,从上面截图可以看出,项目中包含java目录和js目录,我们分开来介绍。
4.2.2.1、java相关介绍
首先我们先看下java目录下,包括 MyApplication、MainAbility,其中MyApplication是应用启动时调用的类,重点来看下MainAbility,代码如下:
很明显可以看到,MainAbility是继承AceAbility,而AceAbility类是JS FA在HarmonyOS上运行环境的基类,继承自Ability。从实现的接口上看没有类似于加载Page的设置,那系统是如何加载JS FA呢?
JS FA生命周期事件分为应用生命周期和页面生命周期,应用通过AceAbility类中setInstanceName(String name)接口设置该Ability的实例资源,并通过AceAbility窗口进行显示以及全局应用生命周期管理。
setInstanceName(String name) :参数name指实例名称,实例的名称与config.json文件中的module.js.name的值对应。创建项目时默认的实例名称是default,因为是默认值,如果使用了缺省值default,则无需调用此接口,就可以默认加载default下的页面。如果你修改了实例名称,则需要在应用Ability实例的onStart()中调用setInstanceName(String name),并将参数“name”设置为修改后的实例名称。
需要注意:在调用setInstanceName(String name)接口时,需要在Ability实例onStart()接口中的super.onStart()之前调用。例如,js的实例名称为:“JSShopping”则调用方式如下:
4.2.2.2、js相关介绍
官方介绍:基于JS扩展的类Web开发范式
项目目录中
|–i18n:存放多语言的json文件
|–pages:存放多个页面,每个页面由hml、css和js文件组成,HML(HarmonyOS Markup Language)是一套类HTML的标记语言。通过组件、事件构建出页面的内容。页面具备数据绑定、事件绑定、列表渲染、条件渲染等高级能力。
|–common:存放图片等资源文件
用于用户交互的界面就位于 main > js > default > pages > index > index.hml,此文件定义了index页面的布局、index页面中用到的组件,以及这些组件的层级关系。例如:index.hml文件中包含了一个text组件,内容为“Hello World”文本。
之后我们就会修改此界面的布局,实现两个输入框和一个计算按钮,实现用户输入两个数字,计算两个数的乘积。此处省略对应的 index.js、index.css的介绍,在文章最后会附上相关的代码。
4.2.3、创建JS FA
4.2.3.1、index.hml
解析:页面上显示两个输入框(input),类型为数字(date),一个按钮(button),按钮的文本为“计算”,在输入框中绑定了onchange的监听器,用于用户输入的数字,按钮上绑定了点击事件onclick,用于触发只需JS FA调用PA,完成两个数相乘的计算。
4.2.3.2、index.js
- oneNumberChange和secondNumberChange用于监听输入框中的内容变化,并缓存变化的内容。
- calculateCount触发JS FA调用PA,FeatureAbility.callAbility(action)其中action设置了相关的参数如下表所示
参数名称 | 类型 | 必填 | 说明 |
---|---|---|---|
bundleName | string | 是 | Ability包的名称,需要与PA端匹配,区分大小写。 |
abilityName | string | 是 | Ability的名称,需要与PA端匹配,区分大小写。 |
messageCode | number | 是 | Ability操作码,操作码定义PA的业务功能,需要与PA端约定 |
abilityType | number | 是 | Ability类型,对应PA端不同的实现方式: 0:Ability,拥有独立的Ability生命周期,FA使用远端进程通信拉起并请求PA服务,适用于提供基本服务供多FA调用或者在后台独立运行的场景;1:Internal Ability,与FA共进程,采用内部函数调用的方式和FA通信,适用于对PA响应时延要求较高的场景,不支持其他FA访问调用能力。 |
data | Object | 否 | 发送到Ability的数据,根据不同的业务携带相应的业务数据,数据字段名称需要与PA端约定 |
syncOption | number | 否 | PA侧请求消息处理同步/异步选项,非必填,默认使用同步方式。当前异步方式仅支持AbilityType为Internal Ability类型。0:同步方式,默认方式。1:异步方式。 |
FeatureAbility.callAbility(action)返回值
类型 | 说明 |
---|---|
Promise<string> | Promise中包含PA返回的结果数据,结果格式为JSON字符串。 |
4.2.3.3、index.css
4.2.4、创建Java PA
4.2.4.1、PA类实现
说明:在main->java->com.nlscan.example目录下创建PA实现类ComputeServiceAbility,ComputeServiceAbility类继承AceInternalAbility,并实现AceInternalAbility.AceInternalAbilityHandler的接口boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption messageOption),在onRemoteRequest中通过JS与PA约定的业务码code区分业务,并实现相关逻辑,代码如下:
4.2.4.2、数据模型 RequestData
说明:在解析JS返回的数据中,根据数据结构定义数据模式类,代码如下:
4.2.4.3 注册和反注册PA
在MainAbility的生命周期中管理PA,onStart()中注册,在onStop中反注册,代码如下:
到此JS FA调用PA以 InternalAbility类型实现的功能就完成了。
五、使用工具自动生成JS FA调用PA
如果你使用的PA实现方式为InternalAbility类型,可以通过工具直接生成相关代码,具体可以查看:是使用工具自动生成JS FA调用PA代码:js2java-codegen
注意:js2java-codegen工具所支持的FA调用PA实现方式为InternalAbility类型,目前尚不支持Ability类型。
六、FA调用PA常见问题的FAQ
6.1、JS调用FeatureAbility.callAbility(OBJECT)返回:“Internal ability not register.”。
回答:返回该错误说明JS接口调用请求未在系统中找到对应的InternalAbilityHandler进行处理,因此需要检查以下几点是否正确执行:
- 在AceAbility继承类中对AceInternalAbility继承类执行了register方法。
- JS侧填写的bundleName和abilityName与AceInternalAbility继承类构造函数中填写的名称保持相同,大小写敏感。
- 检查JS端填写的abilityType(0:Ability; 1:Internal Ability),确保没有将AbilityType缺省或误填写为Ability方式。
七、感谢
如果您能看到最后,还希望您能动动手指点个赞,一个人能走多远关键在于与谁同行,我用跨越山海的一路相伴,希望得到您的点赞。
期待效果展示
学习了