在HarmonyOS上实现ArkTS与H5的交互

介绍

本篇Codelab主要介绍H5如何调用原生侧相关功能,并在回调中获取执行结果。以"获取通讯录"为示例分步讲解JSBridge桥接的实现。

相关概念

Web组件:提供具有网页显示能力的Web组件。

@ohos.web.webview:提供web控制能力。

完整示例

gitee源码地址

源码下载

ArkTS与H5的交互(ArkTS).zip

环境搭建

我们首先需要完成HarmonyOS开发环境搭建,可参照如下步骤进行。

软件要求

DevEco Studio版本:DevEco Studio 3.1 Release。

HarmonyOS SDK版本:API version 9。

硬件要求

设备类型:华为手机或运行在DevEco Studio上的华为手机设备模拟器。

HarmonyOS系统:3.1.0 Developer Release。

环境搭建

安装DevEco Studio,详情请参考下载和安装软件

设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。

如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境

开发者可以参考以下链接,完成设备调试的相关配置:使用真机进行调试

使用模拟器进行调试

代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在源码下载或gitee中提供。

less 复制代码
├──entry/src/main/ets              // 代码区	        
│  ├──common                       // 公共代码区
│  │  ├──constants                 // 公共常量
│  │  │  ├──CodeConstant.ets       // 异步脚本模板
│  │  │  └──CommonConstant.ets     // 公共常量和样式常量
│  │  └──utils                     // 工具类
│  │     ├──JsBridge.ets           // 桥接类
│  │     └──Logger.ets             // 日志类
│  ├──entryability                 
│  │  └──EntryAbility.ets          // 程序入口
│  ├──pages
│  │  └──SelectContact.ets         // 主页面
│  └──viewmodel                    // 项目所需数据类型定义
│     ├──JavaScriptItem.ets        // javaScriptProxy数据格式
│     └──ParamsItem.ets	           // 回调参数数据格式
└──entry/src/main/resources        // 资源入口(rawfile文件夹中存放html)
   └──rawfile
      ├──js              
      │  └──mainPage.js            // H5调用函数文件
      ├──css
      │  └──main.css               // H5样式文件
      └──MainPage.html             // H5页面

ArkTS侧与H5的交互

  1. 首先在开发H5页面(输入框和金额选择部分)前需要实现JSBridge桥接打通两侧的交互。开发者可以在ArkTS侧定义一个JSBridge类,在类中封装call方法以及initJsBridge方法。

  2. 准备异步执行脚本,在脚本中声明一个JSBridgeMap、JSBridgeCallback方法与ohosCallNative对象。并通过runJavaScript在H5端注册ohosCallNative。

  3. 通过Web组件的javaScriptProxy属性将ArkTS侧的call方法以及JSBridgeHandle注册到H5。H5侧调用ohosCallNative对象中的callNative方法,传递func、params以及callback回调。在callNative中保存callback回调。并调用JSBridgeHandle的call方法。

  4. ArkTS侧执行完毕。最后调用runJavaScript方法执行callback,H5侧接收异步回调数据。

4.1 初始化JSBridge

在initJSBridge方法中,通过webviewControll.runJavaScript()将JSBridge初始化脚本注入H5执行。其中callID用来标识H5回调;JSBridgeCallback方法用来执行H5侧回调;window.ohosCallNative对象给H5侧提供调用函数。

ini 复制代码
// CodeConstant.ets

/**
 * 异步执行脚本
*/
export const code = `
  const JSBridgeMap = {};
  let callID = 0;
  
  // 执行H5回调函数
  function JSBridgeCallback (id, params) {
    JSBridgeMap[id](params);
    JSBridgeMap[id] = null;
    delete JSBridgeMap[id];
  }

  // 在window中声明callNative方法供H5调用
  window.ohosCallNative = {
    callNative(method, params, callback) {
      const id = callID++;
      const paramsObj = {
          callID: id,
          data: params || null
      }
      JSBridgeMap[id] = callback || (() => {});
      JSBridgeHandle.call(method, JSON.stringify(paramsObj));
    }
  }
`;

4.2 javaScriptProxy注入

通过Web组件的javaScriptProxy属性,将JSBridgeHandle对象注册到H5侧的window上,作为H5调用原生的通道。

kotlin 复制代码
// JsBridge.ets
export default class JsBridge {
  /**
   * 注入JavaScript对象到window对象中  
   *
   * @returns javaScriptProxy object
   */
  get javaScriptProxy(): JavaScriptItem {
    return {
      object: {
        call: this.call
      },
      name: "JSBridgeHandle",
      methodList: ['call'],
      controller: this.controller
    } as JavaScriptItem;
  }
}

// SelectContact.ets
@Entry
@Component
struct SelectContact {
  webController: WebView.WebviewController = new WebView.WebviewController();
  private jsBridge: JSBridge = new JSBridge(this.webController);

  build() {
    Column() {
      Web({
        src: $rawfile('MainPage.html'),
        controller: this.webController
      })
        .javaScriptAccess(true)
        .javaScriptProxy(this.jsBridge.javaScriptProxy)
        ...
    }
    ...
  }
}

4.3 call方法及callback回调

call方法作为H5调用原生侧接口的统一入口,在该方法中根据H5调用的方法名,匹配到对应的接口后调用,调用结束后通过this.callback()方法,将调用结果回传到H5。

typescript 复制代码
// JsBridge.ets
/**
 * 定义桥接类
 */
export default class JsBridge {
  /**
   * 将ArkTS侧数据传递给call方法
   */
  call = (func: string, params: string): void => {
    const paramsObject: ParamsItem = JSON.parse(params);
    switch (func) {
      case 'chooseContact':
        result = this.chooseContact();
        break;
      default:
        break;
    }
    result.then((data: string) => {
      this.callback(paramsObject?.callID, data);
    })
  }

  /**
   * 将ArkTS侧数据传递到H5
   */
  callback = (id: number, data: string): void => {
    this.controller.runJavaScript(`JSBridgeCallback("${id}", ${JSON.stringify(data)})`);
  }
}

4.4 H5调用ArkTS

实现了上述桥接逻辑后,在H5侧只需要调用ohosCallNative方法,将函数名以及回调函数传递到ArkTS。

javascript 复制代码
// mainPage.js
function chooseContact() {
  window.ohosCallNative.callNative('chooseContact', {}, (data) => {
    ...
  });
}

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. ArkTS侧如何使用桥接通道提供给H5调用方法。

  2. H5如何接收ArkTS侧的异步数据。

相关推荐
国服第二切图仔1 天前
Electron for 鸿蒙PC项目开发之模态框组件
javascript·electron·harmonyos
lichong9511 天前
harmonyos 大屏设备怎么弹出 u 盘
前端·macos·华为·typescript·android studio·harmonyos·大前端
Rene_ZHK1 天前
Day4 AtomGit口袋工具开发1.0
harmonyos
晚霞的不甘1 天前
Flutter 与开源鸿蒙(OpenHarmony)性能调优与生产部署实战:从启动加速到线上监控的全链路优化
flutter·开源·harmonyos
diygwcom1 天前
UniApp 鸿蒙NEXT蓝牙连接及数据写入
华为·uni-app·harmonyos
国服第二切图仔1 天前
Electron for 鸿蒙PC项目实战案例之水果消消乐
javascript·electron·harmonyos·鸿蒙pc
xiaocao_10231 天前
记录在鸿蒙手机的备忘录内容被误删怎么找回?
华为·harmonyos
柒儿吖1 天前
Electron for 鸿蒙PC - 番茄工作法计时器适配问题排查与解决方案
javascript·electron·harmonyos
晚霞的不甘1 天前
Flutter 与开源鸿蒙(OpenHarmony)测试体系构建:从单元测试到真机自动化的一站式质量保障方案
flutter·开源·harmonyos
克喵的水银蛇1 天前
Flutter 入门实战:从零搭建跨平台 HelloWorld 应用(适配鸿蒙 / 安卓 /iOS)
android·flutter·harmonyos