有模有样解决Flutter里Webview无法访问HTTP页面的问题

程序设计实验室

共 3772字,需浏览 8分钟

 ·

2021-06-27 21:51

探索过程

Android9(好像是吧)开始谷歌就默认不让开发者访问不安全HTTP内容了,如果非要用HTTP,那必须在networkSecurityConfig里配置cleartextTrafficPermitted才行。谷歌这个设计的出发点本是好的,HTTPS固然更安全咱都懂,但有时候这个后端接口你选择不了要HTTP还是HTTPS,比如要使用没有提供HTTPS的第三方服务,或者是本文的这种情况:在内嵌的webview里访问没有HTTPS的网页~

正常的Android应用,内嵌个webview,配置一下cleartextTrafficPermitted就可以正常访问HTTP内容了,但是flutter官方的webview组件有点坑,你在flutter项目内的Android工程配置好cleartextTrafficPermitted之后他不管用……

每次遇到HTTP的网页,就会报这个错,很烦

然后这个问题我查了很久也没啥好的解决方案,看到有人给flutter官方提了issues,但是还没解决,那只能自己来强行解决了……

知乎答主的无奈

我的思路是:遇到HTTP地址,直接转成HTTPS来访问,不过这只能解决那些同时有HTTP和HTTPS的网站,遇到只有HTTP的网站就没辙啦~

强行的实现过程

实现的代码很简单,首先利用Webview的onWebViewCreated事件获取WebViewController实例,然后在onPageFinished页面加载完成事件里判断当前页面地址是否http开头,如果是的话就替换成HTTPS并且重新加载即可~

因为http的页面加载在iOS上是白屏,Android上是错误信息,所以为了提高用户体验,我们可以在onPageStarted事件里加入一个加载中的提示框。

做完的效果如下:

涉及的代码如下:

WebView(
  initialUrl: _url,
  allowsInlineMediaPlaybacktrue,
  javascriptMode: JavascriptMode.unrestricted,
  onWebViewCreated(controller) => _webViewController = controller,
  onProgress(value) => print('page progress: $value'),
  onPageStarted: (url) {
    print('onPageStarted: $url');
    if (url.contains('http://')) {
      _httpFlag = true;
      showLoading(context);
    }
  },
  onPageFinished: (value) {
    print('onPageFinished: $value');
    if (value.contains('http://')) {
      setState(() {
        _url = value.replaceAll('http://''https://');
      });
      _webViewController.loadUrl(_url);
    }
    if (value.contains('https://') && _httpFlag) {
      _httpFlag = false;
      Navigator.of(context).pop();
    }
  },
),

比较蠢的解决方法,通过效果图可以看到,对用户体验的提升其实很有限,其实根本是治标不治本的,真要解决这问题还得靠官方~

真正的解决

其实前面说了这么多,真正的解决方案还是靠的flutter官方填坑,好消息是,在最新的flutter2版本中,flutter官方已经成功填坑,现在我们只需要在AndroidManifest.xml里配置好usesCleartextTrafficnetwork_security_config即可!

具体操作就是在flutter项目下创建/android/app/src/main/res/xml/network_security_config.xml文件,填上配置内容:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" />
        </trust-anchors>
    </base-config>
</network-security-config>

然后修改/android/app/src/main/AndroidManifest.xml文件,在application节点加入以下两个属性即可:

android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"

完成之后你的项目结构应该是类似这样的

之后在控制台执行flutter clean,重新run,就可以看到App里的webview能正常打开HTTP网站了,妙啊~

参考资料

  • How to fix 'net::ERR_CLEARTEXT_NOT_PERMITTED' in flutter:https://stackoverflow.com/questions/55592392/how-to-fix-neterr-cleartext-not-permitted-in-flutter
  • 在 Flutter 中使用 WebView:https://zhuanlan.zhihu.com/p/77083307

往期推荐

使用Flutter设计一个好看的"我"页面


Flutter移动应用快速构建实践——状态管理、国际化、数据持久化、性能优化(二)


Flutter开发:迁移Flutter应用到AndroidX



浏览 43
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报