部分机型下,Flutter的flutter_inappwebview在使用evaluateJavascript调用postMessage失败的情况
在上次的调用中, Flutter中,html 与 dart 桥接沟通
flutter_inappwebview的Dart调用html方法,使用的是postMessage方式进行的,如下代码:
// 使用 postMessage 发送
webViewController.evaluateJavascript('''
window.postMessage($message, '*');
''');
但在最近的开发中,发现在部分机型下(目前遇到了:真我手机是这样),这个调用是无效的。
解决方案
通过源码发现:
evaluateJavascript方法中,有2个参数:
- 我们当前使用的source,也就是要执行的js代码
- ContentWorld,这个是可选参数,也就是这段js的作用域。
其中的ContentWorld对象,在注释中表示,Android的实现是通过<iframe>来实现的。也标注了,若需要访问window或document,需要使用window.top和window.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也可以的。
一只孤独的猫咪神!喵!
浙公网安备 33010602011771号