有模有樣解決Flutter里Webview無法訪問HTTP頁面的問題
探索過程
Android9(好像是吧)開始谷歌就默認不讓開發(fā)者訪問不安全HTTP內容了,如果非要用HTTP,那必須在networkSecurityConfig里配置cleartextTrafficPermitted才行。谷歌這個設計的出發(fā)點本是好的,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,
allowsInlineMediaPlayback: true,
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里配置好usesCleartextTraffic和network_security_config即可!
具體操作就是在flutter項目下創(chuàng)建/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節(jié)點加入以下兩個屬性即可:
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"
完成之后你的項目結構應該是類似這樣的
之后在控制臺執(zhí)行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移動應用快速構建實踐——狀態(tài)管理、國際化、數據持久化、性能優(yōu)化(二)

Flutter開發(fā):遷移Flutter應用到AndroidX
