返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
Flutter

A Proper-Looking Solution to Flutter WebView Unable to Access HTTP Pages

The Exploration Process Starting from Android 9 (I think?), Google by default no longer lets developers access insecure HTTP content. If you really need to use HTTP, you must configure cleartextTrafficPermitted in networkSecurityConfig. Google's intention behind this design is good—we all know HTTPS is more secure—but sometimes you don't get to choose whether the backend API is HTTP or HTTPS, for example when using a third-party service that doesn't provide HTTPS, or in the case of this article: in

曦远 (DealiAxy)约 13 分钟
目录5 个章节

The Exploration Process

Starting from Android 9 (I think?), Google by default no longer lets developers access insecure HTTP content. If you really need to use HTTP, you must configure cleartextTrafficPermitted in networkSecurityConfig. Google's intention behind this design is good—we all know HTTPS is more secure—but sometimes you don't get to choose whether the backend API is HTTP or HTTPS, for example when using a third-party service that doesn't provide HTTPS, or in the case of this article: accessing pages without HTTPS in an embedded WebView~

In a normal Android app, embedding a WebView and configuring cleartextTrafficPermitted is enough to access HTTP content. But Flutter's official WebView component is a bit of a trap—after you configure cleartextTrafficPermitted in the Android project inside your Flutter project, it doesn't work...

Every time it hits an HTTP page, it throws this error. Super annoying.

I looked into this problem for a long time and couldn't find a good solution. I saw that someone had filed issues with the Flutter team, but they still hadn't been resolved, so I had to force a solution myself...

My idea: when encountering an HTTP URL, convert it to HTTPS and access that instead. But this only works for sites that have both HTTP and HTTPS; if a site only has HTTP, you're out of luck~

The Forced Implementation

The implementation code is very simple. First, use the WebView's onWebViewCreated event to get a WebViewController instance, then in the onPageFinished page-load-complete event, check whether the current page URL starts with http; if so, replace it with HTTPS and reload~

Because loading an HTTP page results in a white screen on iOS and an error message on Android, to improve the user experience we can add a loading dialog in the onPageStarted event.

The result looks like this:

The relevant code is as follows:

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();
    }
  },
),

A pretty dumb solution. As you can see from the demo, the improvement to user experience is actually quite limited. It's treating the symptom, not the root cause. To really solve this, we still have to rely on the official team~

The Real Solution

After all that talk, the real solution still depends on Flutter officially filling the hole. The good news is that in the latest Flutter 2, the Flutter team has successfully filled it. Now we only need to configure usesCleartextTraffic and network_security_config in AndroidManifest.xml!

The specific steps: create the file /android/app/src/main/res/xml/network_security_config.xml in your Flutter project, and fill in the config:

<?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>

Then modify /android/app/src/main/AndroidManifest.xml, and add the following two attributes to the application node:

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

After that, your project structure should look something like this

Then run flutter clean in the console, run again, and you'll see that the WebView in the app can open HTTP sites normally. Nice~

References

Come Chat

Programming Lab focuses on exploring popular new internet technologies and team agile development practices. Reply with linux, flutter, c#, netcore, android, kotlin, java, python, and so on in the backend of the WeChat official account "Programming Lab" to get related technical articles and materials. If you have any questions, you can also leave a message in the official account backend~

_EOF_

A Proper-Looking Solution to Flutter WebView Unable to Access HTTP Pages

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

初见Flutter!框架简单介绍以及构建可发布的签名Apk包

哈喽!好久不见,算起来我已经一个多月没更新博客了,近期刚刚完成了一个项目,正好抽出时间整理一下学到的东西并且写写博客。 关于flutter 开始使用flutter还是春节后的事情,其实之前很早就想学一下flutter了,毕竟谷歌出的技术总是不会太差的,无奈一直没有时间和做app的需求,这次接触了flutter之后仿佛发现了新大陆,原来开发app还能这么方便,真的颠覆了我原来的认知啊,热更新也太好用

2021-12-18 · Flutter · 约 1 分钟

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

继续上一篇:极简诗词开发背后:Flutter移动应用快速构建实践——状态管理、国际化、数据持久化、性能优化(一) 前文中说到了项目结构、状态管理和国际化的方案,本文继续聊聊数据持久化和粗略的性能优化。 数据持久化 目前的话,flutter用的比较多比较成熟的数据持久化就是shared_preferences和SQFLite,一个是ini配置文件,一个是SQLite数据库,小应用我比较倾向只用前者,

2021-12-18 · Flutter · 约 1 分钟

极简诗词app开发背后:Flutter移动应用快速构建实践——状态管理、国际化、数据持久化、性能优化(一)

前言 在开始之前的提示:虽然Flutter背靠Google这棵大树,但是毕竟还是一个年轻的技术,项目还处于初期阶段,更新非常快,问题也不是一般的多,使用Flutter的话就意味着必须忍受各种奇怪的bug和没有丰富中文资料的头疼,本文不是安利同学们入坑,只是对“极简诗词”app的开发过程进行记录。 另外app已经上架,有兴趣的同学可以下载试试:https://www.coolapk.com/apk/

2022-03-23 · Flutter · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…