部分机型下,Flutter的flutter_inappwebview在使用evaluateJavascript调用postMessage失败的情况

在上次的调用中, Flutter中,html 与 dart 桥接沟通
flutter_inappwebview的Dart调用html方法,使用的是postMessage方式进行的,如下代码:

// 使用 postMessage 发送
webViewController.evaluateJavascript('''
window.postMessage($message, '*');
''');

但在最近的开发中,发现在部分机型下(目前遇到了:真我手机是这样),这个调用是无效的。

解决方案

通过源码发现:
evaluateJavascript方法中,有2个参数:

  1. 我们当前使用的source,也就是要执行的js代码
  2. ContentWorld,这个是可选参数,也就是这段js的作用域。

其中的ContentWorld对象,在注释中表示,Android的实现是通过<iframe>来实现的。也标注了,若需要访问windowdocument,需要使用window.topwindow.top.document来进行。

我使用的是6.1.5的版本,源码 content_world.dart 注释如下:

// ...  这里省略了

// 以下的内容从第3行开始
///Class that represents an object that defines a scope of execution for JavaScript code and which you use to prevent conflicts between different scripts.
///
///**NOTE for iOS**: available on iOS 14.0+. This class represents the native [WKContentWorld](https://developer.apple.com/documentation/webkit/wkcontentworld) class.
///
///**NOTE for Android**: it will create and append an `<iframe>` HTML element with `id` attribute equals to `flutter_inappwebview_[name]`
///to the webpage's content that contains only the inline `<script>` HTML elements in order to define a new scope of execution for JavaScript code.
///Unfortunately, there isn't any other way to do it.
///There are some limitations:
///- for any [ContentWorld], except [ContentWorld.PAGE] (that is the webpage itself), if you need to access to the `window` or `document` global Object,
///you need to use `window.top` and `window.top.document` because the code runs inside an `<iframe>`;
///- also, the execution of the inline `<script>` could be blocked by the `Content-Security-Policy` header.
class ContentWorld {
// ...  这里省略了
}

所以,根据注释的标注,将发送的方法改为:

// 使用 postMessage 发送
webViewController.evaluateJavascript('''
window.top.postMessage($message, '*');
''');

经过测试,可以成功的发送postMessage了。
另:其他使用window.postMessage可以使用的情况,使用window.top.postMessage也同样可以使用,不用做机型判断。iOS也可以的。

posted @ 2026-07-02 13:39  孤独的猫咪神  阅读(8)  评论(0)    收藏  举报