HarmonyOS鸿蒙Next中如何实现 ArkWeb 与原生双向 JS 交互?

HarmonyOS鸿蒙Next中如何实现 ArkWeb 与原生双向 JS 交互?

问题描述

使用 ArkWeb 组件加载网页后,需要让网页 JS 调用鸿蒙原生方法(如获取设备信息),同时鸿蒙原生也需调用网页 JS 函数(如传递用户数据),尝试用webviewController的方法但调用失败,如何实现稳定的双向交互?关键字:ArkWeb、JS 交互、双向通信、webviewController、鸿蒙原生

回答内容

原理解析

ArkWeb 的 JS 交互基于 “原生注入 API + 网页暴露全局函数” 的机制:

  • 原生→JS:通过webviewController.executeScript()调用网页全局 JS 函数;
  • JS→原生:通过webview.setWebMessageListener()监听网页消息,或注入原生 API 供 JS 调用,核心是确保双方通信通道初始化完成后再交互,避免时机过早导致失败。

实现步骤

步骤 1:鸿蒙原生注入 API,供网页 JS 调用
import { webview } from '@kit.ArkWeb';
import common from '@ohos.app.ability.common';

@Entry
@Component
struct ArkWebJSInteraction {
  controller: webview.WebviewController = new webview.WebviewController();
  context = getContext(this) as common.UIAbilityContext;

  build() {
    Column() {
      Web({
        src: $rawfile('test.html'), // 本地网页,也可是远程URL
        controller: this.controller
      })
      .onPageEnd(() => {
        // 网页加载完成后,注入原生API到JS环境
        this.injectNativeApi();
      })
      .webMessageListener((message) => {
        // 监听JS发送的消息(第二种交互方式)
        console.log('JS发送的消息:', message);
        // 回复JS
        this.controller.postMessageToWeb({ type: 'reply', data: '收到消息' });
      })
    }
  }

  // 注入原生API供JS调用
  injectNativeApi() {
    const nativeApi = {
      // 原生方法:获取设备型号
      getDeviceModel: () => {
        return 'HarmonyOS Device'; // 实际可通过系统API获取真实设备信息
      },
      // 原生方法:打开原生弹窗
      showNativeDialog: (title: string, content: string) => {
        promptAction.showDialog({ title, message: content });
      }
    };

    // 注入API到JS的window对象下,命名为nativeApi
    this.controller.executeScript({
      script: `window.nativeApi = ${JSON.stringify(nativeApi)};`
    }).then(() => {
      console.log('原生API注入成功');
    }).catch((err) => {
      console.error('注入失败:', err);
    });
  }
}
步骤 2:网页 JS 调用原生 API + 暴露函数供原生调用

创建src/main/resources/rawfile/test.html

<!DOCTYPE html>
<html>
<body>
  <button onclick="callNativeApi()">调用原生方法</button>
  <script>
    // 1. JS调用鸿蒙原生注入的API
    function callNativeApi() {
      // 调用原生的getDeviceModel方法
      const model = window.nativeApi.getDeviceModel();
      alert('设备型号:' + model);
      // 调用原生的弹窗方法
      window.nativeApi.showNativeDialog('JS调用', '这是JS触发的原生弹窗');
      // 向原生发送消息(通过webMessageListener监听)
      window.harmony.postMessage({ type: 'request', data: '需要用户信息' });
    }

    // 2. 暴露全局函数,供鸿蒙原生调用
    window.jsFunction = function(data) {
      alert('原生调用JS函数,参数:' + JSON.stringify(data));
      return 'JS函数执行成功'; // 可返回结果给原生
    };
  </script>
</body>
</html>
步骤 3:鸿蒙原生调用网页 JS 函数
// 在需要调用的时机(如按钮点击)执行
callJsFunction() {
  // 调用网页的全局函数jsFunction,并传递参数
  this.controller.executeScript({
    script: `window.jsFunction({ name: '鸿蒙', type: 'native' })`
  }).then((result) => {
    console.log('JS函数返回结果:', result);
  }).catch((err) => {
    console.error('调用JS失败:', err);
  });
}

避坑提醒

  • 必须在onPageEnd(网页加载完成)后注入 API / 调用 JS,否则window对象未初始化;
  • 注入的原生方法仅支持序列化数据(JSON 可解析类型),不能传递复杂对象;
  • 远程网页需确保src是 HTTPS 协议(或配置网络安全策略允许 HTTP),否则可能被拦截;
  • 若调用失败,检查是否开启了incognitoMode(隐私模式下部分交互可能受限)。

更多关于HarmonyOS鸿蒙Next中如何实现 ArkWeb 与原生双向 JS 交互?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS Next中,ArkWeb与原生双向JS交互主要通过WebMessagePortWebMessage实现。在ArkTS侧,通过WebController获取WebMessagePort对象,使用postMessage()发送消息到Web侧。在Web侧,通过window.ohWebMessage接收并处理消息,也可通过postMessage()回传数据。ArkTS侧通过onMessageEvent()监听并接收Web侧消息。

更多关于HarmonyOS鸿蒙Next中如何实现 ArkWeb 与原生双向 JS 交互?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,ArkWeb与原生实现双向JS交互的核心是正确使用webviewController的注入和通信机制。您提供的方案基本正确,但需要注意几个关键点:

  1. JS调用原生:通过webviewController.executeScript()注入window.nativeApi对象是标准做法。但需确保注入时机在onPageEnd之后,避免网页未加载完成。

  2. 原生调用JS:使用executeScript()调用全局函数window.jsFunction()可行,但要注意参数传递需为JSON可序列化数据。

  3. 双向通信补充:除了注入API,还可以使用webMessageListener进行消息通信。网页端通过window.harmony.postMessage()发送,原生端通过webMessageListener接收并可用postMessageToWeb()回复。

常见问题排查:

  • 确保controller实例一致,避免多个controller混用。
  • 远程网页需处理跨域限制,本地网页路径需正确。
  • 注入的API方法需返回Promise或同步可序列化值,不支持回调函数参数。

您提供的代码示例已覆盖主要场景,注意executeScript的script字符串中变量替换需谨慎,避免注入漏洞。实际设备信息获取应使用@ohos.deviceInfo等系统API。

回到顶部