Android WebView 診斷與排查問題的方法和技巧
- 2020 年 1 月 19 日
- 筆記
WebView,是Android中很重要的一個組件,我們的應用中集成WebView後,可能會遇到各種各樣的問題,這裡簡單介紹一些Android WebView 診斷與排查問題的方法,希望對於大家有這方面的問題的朋友有所幫助。
開啟DiagnosableWebViewClient日誌輸出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package com.droidyue.webview.webviewclient import android.net.http.SslError import android.webkit.* import com.droidyue.common.debugMessage import com.droidyue.webview.ext.toSimpleString /** * 診斷(錯誤資訊)的WebViewClient,會以日誌輸出形式輸出錯誤資訊,便於發現網頁的問題 */ open class DiagnosableWebViewClient : WebViewClient() { override fun onReceivedError(view: WebView?, errorCode: Int, description: String?, failingUrl: String?) { super.onReceivedError(view, errorCode, description, failingUrl) debugMessage("onReceivedError", "errorCode", errorCode, "description", description, "failingUrl", failingUrl, "webview.info", view?.toSimpleString()) } override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) { super.onReceivedError(view, request, error) debugMessage("onReceivedError", "request", request?.toSimpleString(), "error", error?.toSimpleString(), "webview.info", view?.toSimpleString()) } override fun onSafeBrowsingHit(view: WebView?, request: WebResourceRequest?, threatType: Int, callback: SafeBrowsingResponse?) { super.onSafeBrowsingHit(view, request, threatType, callback) debugMessage("onSafeBrowsingHit", "request", request?.toSimpleString(), "threatType", threatType, "webview.info", view?.toSimpleString()) } override fun onReceivedHttpError(view: WebView?, request: WebResourceRequest?, errorResponse: WebResourceResponse?) { super.onReceivedHttpError(view, request, errorResponse) debugMessage("onReceivedHttpError", "request", request, "errorResponse", errorResponse?.toSimpleString(), "webview.info", view?.toSimpleString()) } override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) { super.onReceivedSslError(view, handler, error) debugMessage("onReceivedSslError", "error", error, "webview.info", view?.toSimpleString()) } } |
---|
舉個例子
WebView頁面出現了白屏,不展示任何內容,如下圖

利用上面支援的內容,我們查看錯誤輸出日誌
1 2 3 |
D debugMessage: ConcreteWebViewClient;onReceivedSslError error primary error: 3 certificate: Issued to: CN=sni.cloudflaressl.com,O=Cloudflare, Inc.,L=San Francisco,ST=CA,C=US; D debugMessage: Issued by: C=NZ,ST=Auckland,L=Auckland,O=XK72 Ltd,OU=https://charlesproxy.com/ssl,CN=Charles Proxy CA (4 Sep 2018, bogon); D debugMessage: on URL: https://droidyue.com/ webview.info url=https://droidyue.com/;originalUrl=null |
---|
通過查找源碼(SslError.java)我們了解到
- errorCode 為 3,代表證書不信任。
這其中的緣由是
- 我們在設備上安裝的charles證書,屬於用戶添加的證書
- 出於應用安全的目的,Android 7及之後默認不信任用戶添加的證書(Android 7 之前是默認信任用戶添加的證書)
- 當我們將App的編譯目標提到24及其以上,系統就會激活這一安全限制。
所以,我們按照這篇文章解決Android手機連接Charles Unknown問題的方案,允許App在debug版本下信任用戶證書就可以解決問題了。
Console日誌查看
比如,我們有這樣一段Javascript程式碼處理console輸出。
1 2 3 4 5 |
console.debug("console.debug"); console.log("console.log"); console.info("console.info"); console.warn("console.warn"); console.error("console.error") |
---|
我們使用
1 |
adb logcat | grep "chromium" –line-buffered –color=always | grep CONSOLE –color=always |
---|
可以過濾出WebView CONSOLE的日誌輸出
1 2 3 4 5 |
I chromium: [INFO:CONSOLE(2)] "console.debug", source: (2) I chromium: [INFO:CONSOLE(3)] "console.log", source: (3) I chromium: [INFO:CONSOLE(4)] "console.info", source: (4) I chromium: [INFO:CONSOLE(5)] "console.warn", source: (5) I chromium: [INFO:CONSOLE(6)] "console.error", source: (6) |
---|
但是這樣也有一個不足,就是沒有列印出Console的消息級別(都展示成了INFO:CONSOLE)。
如果想要解決上面的不足或者自定義日誌輸出關鍵字的話,可以重寫實現WebChromeClient的onConsoleMessage
方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.droidyue.webview.chromeclient import android.webkit.ConsoleMessage import android.webkit.WebChromeClient import com.droidyue.common.debugMessage import com.droidyue.webview.ext.toSimpleString open class DiagnosableChromeClient: WebChromeClient() { override fun onConsoleMessage(message: String?, lineNumber: Int, sourceID: String?) { //不需要調用super方法 debugMessage("onConsoleMessage", "message", message, "lineNumber", lineNumber, "sourceID", sourceID) } override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean { debugMessage("onConsoleMessage", "message", consoleMessage?.toSimpleString()) //返回true,不再需要webview內部處理 return true } } |
---|
1 2 3 4 5 |
D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=TIP;message=console.debug;sourceId=;lineNumber=1 D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=LOG;message=console.log;sourceId=;lineNumber=2 D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=LOG;message=console.info;sourceId=;lineNumber=3 D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=WARNING;message=console.warn;sourceId=;lineNumber=4 D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=ERROR;message=console.error;sourceId=;lineNumber=5 |
---|
開啟 WebView 遠程調試
從Android Kitkat(4.4)開始,WebView 支援與Chrome 連接執行遠程調試。
開啟很簡單,如下程式碼
1 2 3 4 5 |
fun WebView.enableRemoteDebugging() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && BuildConfig.DEBUG) { WebView.setWebContentsDebuggingEnabled(true) } } |
---|
但需要注意兩點
- 一定要限定運行設備大於等於4.4系統
- 強烈建議限定在Debug編譯(或等同條件)包下開啟,不建議Release包也啟用該功能
配置完成後,啟動App,打開Chrome,輸入chrome://inspect

可以調試的功能有
- 審查元素
- 執行Javascript
- 查看網頁資源
- 進行性能分析
- 其他功能
具體內容可以訪問https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews了解。