升级 HTTPS 后 Android WebView 无法加载图片
问题
前端组例行发布网页数小时候后,突然间 Android 打不开网页中的图片了。IOS 也有一些其他问题。然而通过微信和浏览器打开网页是完全正常的。
分析
通过 Charles 抓包,发现 Android WebView 在加载网页时,请求了网页的文本数据,但并未请求图片。分析网页文本数据,看到网页中的 图片地址是 HTTP 的,以为 WebView 应该可以正常加载 HTTP 资源的,并未深究。
估计 bug 和升级 HTTPS 有关,于是先重写了 WebViewClient.onReceivedSslError 方法试试,然而并无效果。
继续研究看是否有其他线索,看到 chromium 输出的 log 后意识到网页是 HTTPS 时,其请求的资源数据也应该是 HTTPS。
chromium log 如下
I/chromium: [INFO:CONSOLE(0)] "Mixed Content: The page at 'https://*' was loaded over HTTPS, but requested an insecure image 'http://****3a.jpg_1483706839'. This request has been blocked; the content must be served over HTTPS.", source: https://*.***.com/#!/?ids=** (0)
解决
有了 log 和确定问题所在就好改了。代码如下
webView.setWebViewClient(new WebViewClient(){
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error){
handler.proceed();
}
});
Android webview 从 Lollipop 开始默认不允许MixedCotentMode,还需要做以下修改
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { webview.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
后台整体更换图片资源 HTTP 链接为 HTTPS 后 ,老版本 APP 打开网页也可以显示图片了。
总结
- WebView加载网页 出问题时分析网页源码和抓包比较麻烦,可以通过看 chromium log来直观的分析问题。
- 第一天上线 HTTPS,第二天傍晚才出现问题,期间有二十多小时,有点奇怪 CDN 缓存时间有那么长么。
2017年01月08日更
只用开启 MixedCotentMode
就可以满足需求了,不需要 handler.proceed()
。
直接 handler.proceed()
太粗暴,Google Play 会警告。