HarmonyOS鸿蒙Next中使用WebMessagePort给Vue侧的H5通信失败

HarmonyOS鸿蒙Next中使用WebMessagePort给Vue侧的H5通信失败 【问题描述】:我们的登录页面是网页然后和客户端做交互,如果用户不勾选协议,点击登录,需要通信到H5,目前我是用的WebMessagePort发送消息,且参考的代码是这个:https://gitee.com/harmonyos_samples/accountkit-samplecode-clientdemo-h5/blob/master/entry/src/main/ets/pages/LoginPage.ets

【问题现象】:现在遇到一个客户端和H5链接成功,客户端也能收到H5发的消息,但给H5发消息 ,H5收不到

cke_8401.png cke_8967.png cke_9847.png

【版本信息】:6.0

【复现代码】:

【尝试解决方案】:


更多关于HarmonyOS鸿蒙Next中使用WebMessagePort给Vue侧的H5通信失败的实战教程也可以访问 https://www.itying.com/category-93-b0.html

6 回复

你好,根据官网代码和您的示例截图来看,可能和您的 that.handleMessageFromNative() 有关;

h5Port.onmessage 回调事件中的function存在一个参数 event(参数来自于handleMessage),导致下面调用中’data’不存在。

您可以发一下handleMessageFromNative函数的代码这边看下;

更多关于HarmonyOS鸿蒙Next中使用WebMessagePort给Vue侧的H5通信失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


handleMessageFromNative(event) {
  console.log('📨 收到客户端消息', event.data);

  try {
    // 解析JSON消息
    const eventData = JSON.parse(event.data);
    const eventId = eventData.eventId;
    const value = eventData.value;

    // 根据事件ID进行处理
    switch (eventId) {
      case 'loginStart':
        // 登录开始
        console.log('🔄 华为登录开始...');
        // showLoading();
        break;

      case 'loginEnd':
        // 登录结束
        console.log('✅ 华为登录结束');
        // hideLoading();
        break;

      case 'notAccepted':
        // 用户未勾选协议
        console.log('⚠️ 用户未同意协议');
        // hideLoading();
        // showAgreementDialog();
        break;

      default:
        console.log('ℹ️ 未处理的事件', { eventId, value });
    }
  } catch (error) {
    console.log('❌ 解析客户端消息失败', error.message);
  }
}
this.h5Port.onmessage = that.handleMessageFromNative(event);

解决了,谢谢,

在HarmonyOS Next中,使用WebMessagePort与Vue侧H5通信失败,可能原因包括:WebMessagePort未正确初始化或配对;端口未在ArkTS侧通过postMessage发送给H5;H5侧未通过onmessage事件监听接收消息;消息传递的数据格式不符合要求;或Web组件未启用JavaScript支持。需确保两端端口建立连接且消息监听机制正确。

根据您提供的代码截图和描述,问题核心在于 ArkTS侧(客户端)向Vue H5侧发送消息失败,而反向通信(H5向ArkTS)是成功的。这通常是由于通信时机或端口状态问题导致的。

结合您参考的示例代码,最可能的原因是:在H5侧尚未完成对WebMessagePort的监听设置时,ArkTS侧就已经尝试发送了消息。

关键问题分析

在您提供的H5代码片段中,window.onload 事件里通过 setupWebViewJavascriptBridge 来设置接收桥接。这是一个异步过程。如果ArkTS侧在H5页面加载后、但setupWebViewJavascriptBridge回调执行之前就调用了postMessage(),消息将会丢失,因为此时H5侧还没有注册监听器。

解决方案

确保通信建立在双向通道都已准备就绪的基础上。推荐以下两种方案:

方案一:在ArkTS侧等待H5的“就绪”信号(推荐且更可靠) 这是示例代码中使用的模式。修改您的H5和ArkTS侧代码,让H5在初始化完成后主动通知ArkTS。

  1. H5侧 (Vue) 修改:setupWebViewJavascriptBridge的回调函数中,或window.onload的最后,主动向ArkTS发送一个“初始化完成”或“准备就绪”的消息。

    // 例如,在setupWebViewJavascriptBridge的回调中
    setupWebViewJavascriptBridge(function(bridge) {
        // ... 其他初始化代码
        // 通知ArkTS,H5已准备好接收消息
        bridge.send('h5_ready', {data: 'H5初始化完成'}, function(responseData) {
            console.log('ArkTS收到就绪信号并回复:', responseData);
        });
    });
    
  2. ArkTS侧修改:onMessage回调中监听这个特定的“就绪”消息。只有收到此消息后,才将用于向H5发送消息WebMessagePort实例保存起来,并在此之后进行业务消息的发送。

    // 在您的ArkTS WebView组件中
    import web_webview from '@ohos.web.webview';
    
    @State messagePort: web_webview.WebMessagePort | null = null;
    
    aboutToAppear(): void {
        // ... 创建WebMessagePort对,并关联到WebView ...
        let ports: web_webview.WebMessagePort[] = this.webviewController.createWebMessagePorts();
        this.webviewController.postMessage('initPort', [ports[1]], '*');
    
        // 设置消息监听
        ports[0].onMessage((event: web_webview.WebMessage) => {
            let message = JSON.parse(event.data as string);
            console.info('ArkTS收到H5消息:', message);
    
            // *** 关键步骤:监听H5的“就绪”信号 ***
            if (message.type === 'h5_ready') {
                // 收到就绪信号,保存用于主动发送消息的端口
                this.messagePort = ports[0];
                // 可以回复一个确认
                this.messagePort.postMessage(JSON.stringify({type: 'ack', data: 'ArkTS已就绪'}));
                console.info('H5已就绪,ArkTS发送端口准备完毕。');
            }
            // ... 处理其他业务消息 ...
        });
    }
    
    // 您的登录协议检查函数
    onLoginButtonClick() {
        if (!this.isAgreementChecked) {
            // 在发送前检查端口是否已就绪
            if (this.messagePort) {
                let msg = {type: 'protocol_not_checked', data: '请勾选用户协议'};
                this.messagePort.postMessage(JSON.stringify(msg));
                console.info('ArkTS已向H5发送协议提醒消息');
            } else {
                console.error('无法发送消息:H5通信端口尚未就绪');
                // 可以在这里给用户一个提示,或尝试重新建立连接
            }
        } else {
            // ... 执行登录 ...
        }
    }
    

方案二:延迟ArkTS侧的首次发送(备选) 如果不想修改H5代码,可以在ArkTS侧使用一个短暂的延迟,确保H5有足够时间完成初始化。这种方法可靠性较低,但在简单场景中可能有效。

// 在aboutToAppear或WebView加载完成后的回调中
setTimeout(() => {
    // 首次发送消息,例如一个握手消息
    ports[0].postMessage(JSON.stringify({type: 'handshake'}));
}, 1000); // 延迟1秒,具体时间需要根据H5加载速度调整

总结

您遇到的问题是典型的双向通信同步问题。请优先采用方案一,通过让H5侧发送“就绪”信号来同步两端状态,这是构建稳定Hybrid通信的常规做法。检查并确保您的WebMessagePort配对、postMessage的调用时机与示例代码逻辑一致,并重点关注消息监听器注册与消息发送的先后顺序。

回到顶部