当前位置:   article > 正文

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

harmonyos 使用java 和 js 开发

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。

  1. // abilityType: 0-Ability; 1-Internal Ability
  2. const ABILITY_TYPE_EXTERNAL = 0;
  3. const ABILITY_TYPE_INTERNAL = 1;
  4. // syncOption(Optional, default sync): 0-Sync; 1-Async
  5. const ACTION_SYNC = 0;
  6. const ACTION_ASYNC = 1;
  7. const ACTION_MESSAGE_CODE_PLUS = 1001;
  8. export default {
  9. plus: async function() {
  10. var actionData = {};
  11. actionData.firstNum = 1024;
  12. actionData.secondNum = 2048;
  13. var action = {};
  14. action.bundleName = 'com.example.hiaceservice';
  15. action.abilityName = 'com.example.hiaceservice.ComputeServiceAbility';
  16. action.messageCode = ACTION_MESSAGE_CODE_PLUS;
  17. action.data = actionData;
  18. action.abilityType = ABILITY_TYPE_EXTERNAL;
  19. action.syncOption = ACTION_SYNC;
  20. var result = await FeatureAbility.callAbility(action);
  21. var ret = JSON.parse(result);
  22. if (ret.code == 0) {
  23. console.info('plus result is:' + JSON.stringify(ret.abilityResult));
  24. } else {
  25. console.error('plus error code:' + JSON.stringify(ret.code));
  26. }
  27. }
  28. }
  • PA端(Ability方式)

功能代码实现:

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

  1. package com.example.hiaceservice;
  2. // ohos相关接口包
  3. import ohos.aafwk.ability.Ability;
  4. import ohos.aafwk.content.Intent;
  5. import ohos.hiviewdfx.HiLog;
  6. import ohos.hiviewdfx.HiLogLabel;
  7. import ohos.rpc.IRemoteBroker;
  8. import ohos.rpc.IRemoteObject;
  9. import ohos.rpc.RemoteObject;
  10. import ohos.rpc.MessageParcel;
  11. import ohos.rpc.MessageOption;
  12. import ohos.utils.zson.ZSONObject;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. public class ComputeServiceAbility extends Ability {
  16. // 定义日志标签
  17. private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "MY_TAG");
  18. private MyRemote remote = new MyRemote();
  19. // FA在请求PA服务时会调用Ability.connectAbility连接PA,连接成功后,需要在onConnect返回一个remote对象,供FA向PA发送消息
  20. @Override
  21. protected IRemoteObject onConnect(Intent intent) {
  22. super.onConnect(intent);
  23. return remote.asObject();
  24. }
  25. class MyRemote extends RemoteObject implements IRemoteBroker {
  26. private static final int SUCCESS = 0;
  27. private static final int ERROR = 1;
  28. private static final int PLUS = 1001;
  29. MyRemote() {
  30. super("MyService_MyRemote");
  31. }
  32. @Override
  33. public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
  34. switch (code) {
  35. case PLUS: {
  36. String dataStr = data.readString();
  37. RequestParam param = new RequestParam();
  38. try {
  39. param = ZSONObject.stringToClass(dataStr, RequestParam.class);
  40. } catch (RuntimeException e) {
  41. HiLog.error(LABEL, "convert failed.");
  42. }
  43. // 返回结果当前仅支持String,对于复杂结构可以序列化为ZSON字符串上报
  44. Map<String, Object> result = new HashMap<String, Object>();
  45. result.put("code", SUCCESS);
  46. result.put("abilityResult", param.getFirstNum() + param.getSecondNum());
  47. reply.writeString(ZSONObject.toZSONString(result));
  48. break;
  49. }
  50. default: {
  51. Map<String, Object> result = new HashMap<String, Object>();
  52. result.put("abilityError", ERROR);
  53. reply.writeString(ZSONObject.toZSONString(result));
  54. return false;
  55. }
  56. }
  57. return true;
  58. }
  59. @Override
  60. public IRemoteObject asObject() {
  61. return this;
  62. }
  63. }
  64. }

请求参数代码:

RequestParam.java

  1. public class RequestParam {
  2. private int firstNum;
  3. private int secondNum;
  4. public int getFirstNum() {
  5. return firstNum;
  6. }
  7. public void setFirstNum(int firstNum) {
  8. this.firstNum = firstNum;
  9. }
  10. public int getSecondNum() {
  11. return secondNum;
  12. }
  13. public void setSecondNum(int secondNum) {
  14. this.secondNum = secondNum;
  15. }
  16. }

PA端(Internal Ability方式)

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

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

  1. package com.example.hiaceservice;
  2. // ohos相关接口包
  3. import ohos.ace.ability.AceInternalAbility;
  4. import ohos.app.AbilityContext;
  5. import ohos.hiviewdfx.HiLog;
  6. import ohos.hiviewdfx.HiLogLabel;
  7. import ohos.rpc.IRemoteObject;
  8. import ohos.rpc.MessageOption;
  9. import ohos.rpc.MessageParcel;
  10. import ohos.rpc.RemoteException;
  11. import ohos.utils.zson.ZSONObject;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. public class ComputeInternalAbility extends AceInternalAbility {
  15. private static final String BUNDLE_NAME = "com.example.hiaceservice";
  16. private static final String ABILITY_NAME = "com.example.hiaceservice.ComputeInternalAbility";
  17. private static final int SUCCESS = 0;
  18. private static final int ERROR = 1;
  19. private static final int PLUS = 1001;
  20. // 定义日志标签
  21. private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "MY_TAG");
  22. private static ComputeInternalAbility instance;
  23. private AbilityContext abilityContext;
  24. // 如果多个Ability实例都需要注册当前InternalAbility实例,需要更改构造函数,设定自己的bundleName和abilityName
  25. public ComputeInternalAbility() {
  26. super(BUNDLE_NAME, ABILITY_NAME);
  27. }
  28. public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
  29. switch (code) {
  30. case PLUS: {
  31. String dataStr = data.readString();
  32. RequestParam param = new RequestParam();
  33. try {
  34. param = ZSONObject.stringToClass(dataStr, RequestParam.class);
  35. } catch (RuntimeException e) {
  36. HiLog.error(LABEL, "convert failed.");
  37. }
  38. // 返回结果当前仅支持String,对于复杂结构可以序列化为ZSON字符串上报
  39. Map<String, Object> result = new HashMap<String, Object>();
  40. result.put("code", SUCCESS);
  41. result.put("abilityResult", param.getFirstNum() + param.getSecondNum());
  42. // SYNC
  43. if (option.getFlags() == MessageOption.TF_SYNC) {
  44. reply.writeString(ZSONObject.toZSONString(result));
  45. } else {
  46. // ASYNC
  47. MessageParcel responseData = MessageParcel.obtain();
  48. responseData.writeString(ZSONObject.toZSONString(result));
  49. IRemoteObject remoteReply = reply.readRemoteObject();
  50. try {
  51. remoteReply.sendRequest(0, responseData, MessageParcel.obtain(), new MessageOption());
  52. } catch (RemoteException exception) {
  53. return false;
  54. } finally {
  55. responseData.reclaim();
  56. }
  57. }
  58. break;
  59. }
  60. default: {
  61. Map<String, Object> result = new HashMap<String, Object>();
  62. result.put("abilityError", ERROR);
  63. reply.writeString(ZSONObject.toZSONString(result));
  64. return false;
  65. }
  66. }
  67. return true;
  68. }
  69. /**
  70. * Internal ability 注册接口。
  71. */
  72. public static void register(AbilityContext abilityContext) {
  73. instance = new ComputeInternalAbility();
  74. instance.onRegister(abilityContext);
  75. }
  76. private void onRegister(AbilityContext abilityContext) {
  77. this.abilityContext = abilityContext;
  78. this.setInternalAbilityHandler((code, data, reply, option) -> {
  79. return this.onRemoteRequest(code, data, reply, option);
  80. });
  81. }
  82. /**
  83. * Internal ability 注销接口。
  84. */
  85. public static void unregister() {
  86. instance.onUnregister();
  87. }
  88. private void onUnregister() {
  89. abilityContext = null;
  90. this.setInternalAbilityHandler(null);
  91. }
  92. }

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

  1. public class MainAbility extends AceAbility {
  2. @Override
  3. public void onStart(Intent intent) {
  4. // 注册, 如果需要在Page初始化(onInit或之前)时调用AceInternalAbility的能力,注册操作需要在super.onStart之前进行
  5. ComputeInternalAbility.register(this);
  6. ...
  7. super.onStart(intent);
  8. }
  9. @Override
  10. public void onStop() {
  11. // 注销
  12. ComputeInternalAbility.unregister();
  13. super.onStop();
  14. }
  15. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/320232
推荐阅读
相关标签
  

闽ICP备14008679号