在进行鸿蒙应用开发中由于每个人的开发习惯不同,鸿蒙官方文档说明中也是支持多种开发方式,今天跟大家聊聊关于 JS 跟 Java 之间混合开发方式。
01 基本介绍
首先是因为我个人习惯使用 JS 进行页面开发布局,但是鸿蒙提供的 Java API 的功能比 JS API 的功能要强大,所以我选择用 JS 开发页面用 Java 实现逻辑交互。
那么这两者之间如何进行通信就是我们需要考虑的问题,好在官方文档中有关于 JS API 调用 Java API 机制的说明。
FA 提供了三个 JS 接口分别为:
- FeatureAbility.callAbility(OBJECT): 调用 PA 能力。
- FeatureAbility.subscribeAbilityEvent(OBJECT, Function): 订阅 PA 能力。
- FeatureAbility.unsubscribeAbilityEvent(OBJECT): 取消订阅 PA 能力。
在 PA 端也有对应的接口其包含远端调用 Ability 和本地调用 Internal Ability 两种方式。
PA 端调用 Ability 接口方式为:
boolean IRemoteObject.onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option);
PA 端调用 Internal Ability 接口方式为:
boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option)
JS 端与 Java 通过接口扩展机制进行通信,通过 bundleName 和 abilityName 进行关联,所以我们要建立两者之间的通信,根据提供的接口字段进行相对应匹配。
接下来通过我写的例子方便大家更好的去理解 JS 是如何调用 PA 能力的。
02 权限配置
本示例需要位置权限,因此在 config.json 中添加以下字段,还有就是需要在手机中打开定位开关:
"reqPermissions": [ { "name": "ohos.permission.LOCATION" }],
03 代码演示
JS 端接口代码如下:其中 messageCode、abilityType、syncOption 值根据文档进行配置。
aa:async function (){
var actionData = {};
actionData.longitude = this.longitude;
actionData.latitude = this.latitude;
var action = {};
action.data = actionData;
action.bundleName = 'com.example.shundaschool';
action.abilityName = 'com.example.shundaschool.LocationAbility';
action.messageCode = 666;
action.abilityType = 1;
action.syncOption = 1;
var result = await FeatureAbility.callAbility(action);
var ret = JSON.parse(result);
console.info("00000" + ret);
console.info("0022" + JSON.stringify(ret.abilityResult));
this.$set("address",JSON.stringify(ret.abilityResult))
},
PA 端接口代码如下:
... ...
private static final String BUNDLE_NAME = "com.example.shundaschool";
private static final String ABILITY_NAME = "com.example.shundaschool.LocationAbility";
... ...
public LocationAbility() {
super(BUNDLE_NAME, ABILITY_NAME);
}
public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
switch (code) {
case location: {
String zsonStr = data.readString();
RequestParamsss param = ZSONObject.stringToClass(zsonStr, RequestParamsss.class);
System.out.println("我是param经度:"+param.getLatitude());
System.out.println("我是param纬度:"+param.getLongitude());
// 返回结果当前仅支持String,对于复杂结构可以序列化为ZSON字符串上报
GeoConvert geoConvert = new GeoConvert();
try{
List<GeoAddress> address = geoConvert.getAddressFromLocation(param.getLatitude(), param.getLongitude(), 1);
// System.out.println(address);
// System.out.println(address.get(0).getDescriptions(0));
Map<String, Object> zsonResult = new HashMap<String, Object>();
zsonResult.put("code", SUCCESS);
System.out.println("我是param:" + param);
zsonResult.put("abilityResult", address.get(0).getDescriptions(0));
if (option.getFlags() == MessageOption.TF_SYNC) {
reply.writeString(ZSONObject.toZSONString(zsonResult));
} else {
// ASYNC
MessageParcel reponseData = MessageParcel.obtain();
reponseData.writeString(ZSONObject.toZSONString(zsonResult));
IRemoteObject remoteReply = reply.readRemoteObject();
try {
remoteReply.sendRequest(0, reponseData, MessageParcel.obtain(), new MessageOption());
reponseData.reclaim();
} catch (RemoteException exception) {
return false;
}
}
}catch (IOException e){
System.out.println("获取位置信息异常");
}
break;
}
default:{
reply.writeString("service not defined");
}
}
return true;
}
实现效果图展示如下:
点击获取位置信息展示设备经纬度,再次点击查看位置通过逆地址转换展示具体位置:
这两者能够正常进行通信后,这样我们就能够在 JS UI 中进行页面布局,在 Java UI 里进行逻辑处理了,希望以上内容能对大家有所帮助。