ASCF WebView:H5 为什么收不到元服务消息?

ASCF WebView:H5 为什么收不到元服务消息?

H5 调用 postMessage 后返回 success 和 complete,却没有触发 onMessage,是元服务 WebView 通信里最容易误判的问题之一。

关键结论:H5 发送成功只证明 H5 -> 元服务 可用;要验证 元服务 -> H5,必须由元服务使用 has.createWebViewContext().postMessage 发送,并由 H5 的 has.ascfweb.onMessage 接收。

官方参考:WebView 开发 - 元服务服务框架(ASCF)

两条方向,三类 API

方向 发送端 接收端 不能证明什么
H5 -> 元服务 has.ascfweb.postMessage web-view 的 bindmessage 不能证明元服务能向 H5 发消息
元服务 -> H5 has.createWebViewContext().postMessage has.ascfweb.onMessage 这是本文验证的方向

因此,如果 H5 侧打印:

复制代码
postMessage success {}
postMessage complete {}

这只能说明 H5 -> 元服务 成功;并不能说明 H5 的 onMessage 已收到元服务消息。

版本边界:不要混淆三个版本

层级 本文版本/要求 含义
ASCF 框架 2.0.4+ 官方 API 页面明确标注:has.ascfweb.onMessage 的起始版本为 2.0.4。
H5 JS SDK @atomicservice/ascf-web-sdk 1.0.8 本次真机验证实际使用的 H5 SDK。
元服务 API 包 @atomicservice/ascfapi:声明 ^1.0.6,锁定 1.0.23 元服务 ohpm 依赖。
HarmonyOS SDK 5.0.0(12) 本最小复现工程的 compatibleSdkVersion 和 targetSdkVersion。

重点:

  • has.ascfweb.onMessage 从 ASCF 框架 2.0.4 起支持;低于该版本时不应调用此 API。
  • ASCF 框架 2.0.4+ 不等于 H5 JS SDK 2.0.4。
  • 本文没有把 2.0.4 写到 H5 script 地址中;H5 使用的是 1.0.8。
  • ASCF 运行时 versionCode 不是框架语义化版本,不能拿它替代 2.0.4 的版本判断。

H5 正确写法:初始化时注册接收回调

服务端 H5 页面引入 JS SDK 后,尽早注册回调:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>PostMessage H5</title>
  <script src="ascf-web-sdk.umd.js"></script>
</head>
<body>
  <h1>H5 - has.ascfweb.onMessage</h1>
</body>
<script>
  has.ascfweb.onMessage((data) => {
    console.info('onMessage H5收到来自元服务的消息:', data);
  });
</script>
</html>

监听应放在 H5 初始化阶段,而不是接口请求、按钮点击或延迟定时器之后。不要假设回调注册前的消息会被缓存后补发。

为了看清对象内容,调试时可以额外打印:

js 复制代码
has.ascfweb.onMessage((data) => {
  console.info('H5 received:', JSON.stringify(data));
});

设备控制台把对象显示为 object Object 时,表示回调已收到对象但日志被字符串化,不代表消息失败。

元服务正确写法:使用 WebView 上下文发送

hxml

xml 复制代码
<view class="menu-list">
  <view class="web-view-class">
    <web-view src="{{ url }}"
      bindmessage="onWebviewMessage"
      class="web-view-class"></web-view>
  </view>
  <button bindtap="sendString" type="primary">发送字符串</button>
  <button bindtap="sendSimpleObject" type="primary">发送简单对象消息</button>
</view>

css

css 复制代码
.web-view-class {
  height: 400px;
}

.menu-list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
  padding: 16px;
}

WebView 不能占满整个不可滚动页面,否则原生按钮会被挤出屏幕,表象会变成"发送函数没执行"。

js

js 复制代码
Page({
  data: {
    url: 'https://www.example.com/example.html',
  },

  onWebviewMessage(event) {
    console.info('onWebviewMessage:', JSON.stringify(event));
  },

  sendString() {
    const ctx = has.createWebViewContext();
    ctx.postMessage({
      data: 'Js string message to H5',
      success: () => console.info('postMessage success'),
      fail: (err) => console.error('postMessage fail:', err),
      complete: (res) => console.info('postMessage complete:', res),
    });
  },

  sendSimpleObject() {
    const ctx = has.createWebViewContext();
    ctx.postMessage({
      data: {
        msg: 'JS object message to H5',
        version: '1.0',
      },
      success: () => console.info('postMessage success'),
      fail: (err) => console.error('postMessage fail:', err),
      complete: (res) => console.info('postMessage complete:', res),
    });
  },
});

这里有两个不可替代的关键点:

  1. 调用 has.createWebViewContext() 获取当前 WebView 控制实例。
  2. 调用 ctx.postMessage({ data: ... });业务消息放在 data 字段。

常见错误路径

1. 把 H5 发送成功当作双向成功

H5 的 has.ascfweb.postMessage 成功,验证的只是 H5 -> 元服务。要测试 H5 接收,必须让元服务调用 ctx.postMessage。

2. 未按 ASCF 场景使用 createWebViewContext

不要用其他 WebView 框架的元素实例调用方式替代官方场景中的 has.createWebViewContext().postMessage。发送端可能没有进入 ASCF 的桥接通道。

3. H5 注册 onMessage 过晚

回调未注册时发送消息,不能假设运行时会缓存并补发。因此先注册监听,再执行其它业务初始化。

4. 发送按钮不可见或不可点击

WebView 固定高度过大、页面不能滚动时,按钮在视口之外,元服务侧自然不会出现 postMessage success、fail、complete 日志。

5. URL 被域名管控拦截

H5 必须先被 WebView 成功加载。局域网 HTTP 调试地址若被域名管控拦截或出现 ERR_ABORTED,应先处理服务器域名配置;开发期可按平台规则启用"开发中元服务豁免管控"。

真机验证证据

最小示例在真机上得到:

css 复制代码
onMessage H5收到来自元服务的消息: Js string message to H5
postMessage success
postMessage complete: {}

onMessage H5收到来自元服务的消息: [object Object]
postMessage success
postMessage complete: {}

结论:

  • 字符串消息已由元服务发送,并触发 H5 的 onMessage。
  • 简单对象也已触发 onMessage;对象日志显示为 object Object 属于展示形式。
  • 发送端的 success / complete 与 H5 接收日志同时出现,才是元服务 -> H5 通信成功的完整证据。

发布前检查清单

  • ASCF 框架版本为 2.0.4 或更高;has.ascfweb.onMessage 的官方起始版本是 2.0.4。
  • H5 引入正确版本的 ascf-web-sdk.umd.js。
  • H5 初始化时注册 has.ascfweb.onMessage。
  • 元服务使用 has.createWebViewContext().postMessage({ data })。
  • 元服务记录 success、fail、complete。
  • H5 URL 已通过正式域名管控或调试豁免。
  • WebView 不遮挡发送按钮。

总结

把通信方向拆开,就不会被单侧 success 误导:

css 复制代码
H5 -> 元服务:has.ascfweb.postMessage
元服务 -> H5:has.createWebViewContext().postMessage({ data })
H5 接收:has.ascfweb.onMessage

按官方 WebView 场景使用上下文 API,并确保 ASCF 框架版本满足 2.0.4+ 的能力要求后,H5 可以稳定接收元服务发送的字符串和简单对象消息。

相关推荐
计算机魔术师9 小时前
谷歌搜索广告踩刹车,AI广告成为救命稻草
前端
总要学点什么10 小时前
第81篇:数据可视化-PM2.5分布——让圆点的胖瘦替每座城市报出浓度
前端·信息可视化·echarts·cesium·空间分析
IT_陈寒10 小时前
Vue的v-for里用了个临时变量,页面直接挂了
前端·人工智能·后端
hunter_07610 小时前
一次 iOS 真机签名 409 的完整排查:证书、设备、描述文件为什么总是"对不上"
前端
枣把儿10 小时前
开源!公众号排版+一键发布工具懒人版
前端
2501_9160074710 小时前
抓包工具功能对比,TraceEagle、Charles、Fiddler、Wireshark、mitmproxy 差别
前端·网络协议·ios·adb·https·fiddler·wireshark
Flynt10 小时前
AI 写的页面一眼假?有人把"假指纹"写成 62 条规则,不用大模型就能跑
前端·ai编程·claude
kyriewen10 小时前
我把 10 道面试题答案真跑了一遍:6 道是错的
前端·javascript·面试
WebInfra11 小时前
Rspack 2.3 发布:联手 SWC 团队带来全新编译器
前端·javascript·github
小卿噢11 小时前
同样是插 10 万行,最快的写法比最慢的快 103 倍
前端