Android WebView 诊断与排查问题的方法和技巧

我不是女神ヾ 2023-05-30 03:54 103阅读 0赞

WebView,是安卓中很重要的一个组件,我们的应用中集成WebView后,可能会遇到各种各样的问题,这里简单介绍一些Android WebView 诊断与排查问题的方法,希望对于大家有这方面的问题的朋友有所帮助。

开启DiagnosableWebViewClient日志输出

  1. package com.droidyue.webview.webviewclient
  2. import android.net.http.SslError
  3. import android.webkit.*
  4. import com.droidyue.common.debugMessage
  5. import com.droidyue.webview.ext.toSimpleString
  6. /** * 诊断(错误信息)的WebViewClient,会以日志输出形式输出错误信息,便于发现网页的问题 */
  7. open class DiagnosableWebViewClient : WebViewClient() {
  8. override fun onReceivedError(view: WebView?, errorCode: Int, description: String?, failingUrl: String?) {
  9. super.onReceivedError(view, errorCode, description, failingUrl)
  10. debugMessage("onReceivedError", "errorCode", errorCode, "description", description,
  11. "failingUrl", failingUrl, "webview.info", view?.toSimpleString())
  12. }
  13. override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
  14. super.onReceivedError(view, request, error)
  15. debugMessage("onReceivedError", "request", request?.toSimpleString(), "error", error?.toSimpleString(),
  16. "webview.info", view?.toSimpleString())
  17. }
  18. override fun onSafeBrowsingHit(view: WebView?, request: WebResourceRequest?, threatType: Int, callback: SafeBrowsingResponse?) {
  19. super.onSafeBrowsingHit(view, request, threatType, callback)
  20. debugMessage("onSafeBrowsingHit", "request", request?.toSimpleString(), "threatType", threatType,
  21. "webview.info", view?.toSimpleString())
  22. }
  23. override fun onReceivedHttpError(view: WebView?, request: WebResourceRequest?, errorResponse: WebResourceResponse?) {
  24. super.onReceivedHttpError(view, request, errorResponse)
  25. debugMessage("onReceivedHttpError", "request", request, "errorResponse", errorResponse?.toSimpleString(),
  26. "webview.info", view?.toSimpleString())
  27. }
  28. override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler?, error: SslError?) {
  29. super.onReceivedSslError(view, handler, error)
  30. debugMessage("onReceivedSslError", "error", error, "webview.info", view?.toSimpleString())
  31. }
  32. }

举个例子

WebView页面出现了白屏,不展示任何内容,如下图
在这里插入图片描述
利用上面支持的内容,我们查看错误输出日志

  1. 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;
  2. 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);
  3. 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. console.debug("console.debug");
  2. console.log("console.log");
  3. console.info("console.info");
  4. console.warn("console.warn");
  5. console.error("console.error")

我们使用

  1. adb logcat | grep "chromium" --line-buffered --color=always | grep CONSOLE --color=always

可以过滤出WebView CONSOLE的日志输出

  1. I chromium: [INFO:CONSOLE(2)] "console.debug", source: (2)
  2. I chromium: [INFO:CONSOLE(3)] "console.log", source: (3)
  3. I chromium: [INFO:CONSOLE(4)] "console.info", source: (4)
  4. I chromium: [INFO:CONSOLE(5)] "console.warn", source: (5)
  5. I chromium: [INFO:CONSOLE(6)] "console.error", source: (6)

但是这样也有一个不足,就是没有打印出Console的消息级别(都展示成了INFO:CONSOLE)。

如果想要解决上面的不足或者自定义日志输出关键字的话,可以重写实现WebChromeClient的onConsoleMessage方法

  1. package com.droidyue.webview.chromeclient
  2. import android.webkit.ConsoleMessage
  3. import android.webkit.WebChromeClient
  4. import com.droidyue.common.debugMessage
  5. import com.droidyue.webview.ext.toSimpleString
  6. open class DiagnosableChromeClient: WebChromeClient() {
  7. override fun onConsoleMessage(message: String?, lineNumber: Int, sourceID: String?) {
  8. //不需要调用super方法
  9. debugMessage("onConsoleMessage", "message", message, "lineNumber", lineNumber, "sourceID", sourceID)
  10. }
  11. override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
  12. debugMessage("onConsoleMessage", "message", consoleMessage?.toSimpleString())
  13. //返回true,不再需要webview内部处理
  14. return true
  15. }
  16. }
  17. D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=TIP;message=console.debug;sourceId=;lineNumber=1
  18. D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=LOG;message=console.log;sourceId=;lineNumber=2
  19. D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=LOG;message=console.info;sourceId=;lineNumber=3
  20. D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=WARNING;message=console.warn;sourceId=;lineNumber=4
  21. D debugMessage: ConcreteWebChromeClient;onConsoleMessage message messageLevel=ERROR;message=console.error;sourceId=;lineNumber=5

开启 WebView 远程调试

从Android Kitkat(4.4)开始,WebView 支持与Chrome 连接执行远程调试。

开启很简单,如下代码

  1. fun WebView.enableRemoteDebugging() {
  2. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && BuildConfig.DEBUG) {
  3. WebView.setWebContentsDebuggingEnabled(true)
  4. }
  5. }

但需要注意两点

  • 一定要限定运行设备大于等于4.4系统
  • 强烈建议限定在Debug编译(或等同条件)包下开启,不建议Release包也启用该功能
    配置完成后,启动App,打开Chrome,输入chrome://inspect

发表评论

表情:
评论列表 (有 0 条评论,103人围观)

还没有评论,来说两句吧...

相关阅读