有模有樣解決Flutter里Webview無法訪問HTTP頁面的問題


探索過程

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,
  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里配置好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網站了,妙啊~

參考資料

歡迎交流

程序設計實驗室專注於互聯網熱門新技術探索與團隊敏捷開發實踐,在公眾號「程序設計實驗室」后台回復 linux、flutter、c#、netcore、android、kotlin、java、python 等可獲取相關技術文章和資料,同時有任何問題都可以在公眾號后台留言~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM