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),
});
},
});
这里有两个不可替代的关键点:
- 调用 has.createWebViewContext() 获取当前 WebView 控制实例。
- 调用 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 可以稳定接收元服务发送的字符串和简单对象消息。