flutter_jsbridge_plugin在部分机型与JS交互失效问题

一、背景

将公司原生项目使用Flutter实现,其中与WebView交互这一块,原生用的是JSBridge,为了避免大量改动,决定Flutter端也采用JSBridge,插件flutter_jsbridge_plugin,测试期间发现,在低版本手机,与JS交互方面没问题,但是在高版本手机上,交互全都失效。

二、解决方案

情况一: WebView加载完成之前 无 JS交互

这种情况就比较简单,在该插件的源码中有一个init方法,这个方法就是在执行注入JS的操作。

class JsBridge {
  WebViewController _webViewController;
  Map<String, CallBackFunction> _callbacks = Map();
  Map<String, BridgeHandler> _handlers = Map();
  int _uniqueId = 0;
  static final String _protocolScheme = "jsbridge://";
  final String _fetchData = "${_protocolScheme}return/fetch";
  final String _returnData = "${_protocolScheme}return/sendMsg/";
  String _dartToJs =
      "javascript:WebViewJavascriptBridge._handleMessageFromNative('%s');";

  void loadJs(WebViewController controller) {
    _webViewController = controller;
    init();
  }

  void init() {
    if (_webViewController == null) {
      throw "WebViewController must not null";
    }
    if (Platform.isIOS) {
      _loadJs(init_script_ios);
    } else {
      _loadJs(init_script_android);
    }
//    test();
  }

我们只需要在WebView的状态回调的函数中各进行init一次,保证JS注入是成功的。

WebView(
                  initialUrl: _web_url,

                  javascriptMode: JavascriptMode.unrestricted,

                  onWebViewCreated: (controller) async {
                    _jsBridge.loadJs(controller);
                    _controller.complete(controller);
                    registerWebViewHandler();
                  },

                  navigationDelegate: (NavigationRequest request) {
                    if (_jsBridge.handlerUrl(request.url)) {
                      return NavigationDecision.navigate;
                    }
                    return NavigationDecision.prevent;
                  },

                  onPageStarted: (url) {
                    _jsBridge.init();
                  },
                  
                  onPageFinished:(url) {
                   _jsBridge.init();
                  },

                  onProgress: (value) {
                   
                  },
              );
情况二: WebView加载完成之前 有 JS交互

这种情况一般是在WebView加载完成之前需要传给JS一些数据,目前我没有想到更好的处理方案,只有如下方法暂时处理,如果大家有更好的方案,欢迎在评论区告诉我,感谢!

onProgress: (value) {
                    if (value > 10) {
                      _jsBridge.init();
                    }else if (value > 20){
                      _jsBridge.init();
                    }else if (value > 30){
                      _jsBridge.init();
                    }else if (value > 40){
                      _jsBridge.init();
                    }else if (value > 50){
                      _jsBridge.init();
                    }else if (value > 60){
                      _jsBridge.init();
                    }else if (value > 70){
                      _jsBridge.init();
                    }else if (value > 80){
                       _jsBridge.init();
                    }else if (value > 90){
                      _jsBridge.init();
                    }
                  }

这样就能确保在网页加载完成之前注入JS成功,这种挺不严谨的,希望能有更好的解决方案。

后续

最近将之前使用的官方的webview插件 webview_flutter 替换成了 flutter_inappwebview,使用下来,这个插件比官方插件功能更加完善,并且流畅度更高。

1、flutter_inappwebview内部已经自己兼容了JSBridge,所以使用它,就不需要再接入flutter_jsbridge_plugin,直接按如下代码去交互即可:
onWebViewCreated: (controller) async {
        _controller = controller;
        controller
          ..addJavaScriptHandler(
            handlerName: 'functionName',
// arguments是一个List,如果前端只传了一个元素,那就取arguments的第0个元素
            callback: (arguments) {
              var temp = {};
                return temp;// 用return返回数据给前端
              });
            },
          )
};
2、webview_flutter的Controller中有个setOnShowFileSelector用于监听拦截打开媒体库的事件,需要实现这个方法才能在跨域的h5中监听并手动打开媒体库选择器,而在flutter_inappwebview中也已经被兼容,即便在跨域的h5中依然能打开媒体库。
3、flutter_inappwebview:6.0.0开始,相对于以前的版本,以及webview_flutter,流畅度的提升非常大!强烈推荐使用!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容