【问题标题】:Disable Android WebView/WebViewClient Initiated favicon.ico Request禁用 Android WebView/WebViewClient 发起的 favicon.ico 请求
【发布时间】:2016-01-19 20:44:09
【问题描述】:

当我调用 WebView.loadUrl() 时,如何禁用 Android WebView/WebViewClient 发送对 favicon.ico 的请求?在通过 CharlesProxy 分析请求时,我可以看到正在进行的调用。

我不拥有我在 WebView 中显示的 HTML 内容。我的研究从服务器端获得了很多解决方法的结果,但这些对我不起作用。

【问题讨论】:

    标签: android android-webview favicon webviewclient


    【解决方案1】:

    对我来说,完整的解决方案是:

       @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    
            if(url.toLowerCase().contains("/favicon.ico")) {
                try {
                    return new WebResourceResponse("image/png", null, null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            return null;
        }
    
        @Override
        @SuppressLint("NewApi")
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    
            if(!request.isForMainFrame() && request.getUrl().getPath().endsWith("/favicon.ico")) {
                try {
                    return new WebResourceResponse("image/png", null, null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            return null;
        }
    

    【讨论】:

    • @MilošČernilovský 是正确的答案,而不是将图标放入资产中。似乎是很干净简单正确的做法
    • 附带说明,request.isForMainFrame() 可能没有按照您的预期执行,因为即使是最初加载的包含 iframe 的 URL,它也会返回 false。见:stackoverflow.com/questions/40000939/…
    • 我觉得奇怪的是,在这样做之后,即使我在 Charles 中没有看到任何呼叫,我也会收到一个错误,好像已经拨打了电话并且没有找到图标(这就是发生的事情在删除 favicon 调用之前到应用程序)。我清除了缓存并禁用了它,但它仍然会发生......我知道为什么会这样。此外,无论我在 WebSourceResponse 中传递什么,例如 mimeType,在调用 onReceivedHttpError 或 onReceivedError 时都会显示为空。
    【解决方案2】:

    我通过一个小技巧实现了这一点。首先,我创建了一个假的 1x1 图标文件并将其保存到 assets 文件夹中。然后我覆盖了WebViewClient's shouldInterceptRequest() 方法,在该方法中我检查 URL 是否是对 favicon 文件的请求,在这种情况下返回 WebResourceResponse 和 InputStream ,其中包含我们的假图标:

        @Override
        @CallSuper
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            if(!request.isForMainFrame() && request.getUrl().getPath().equals("/favicon.ico")) {
                try {
                    return new WebResourceResponse("image/png", null, new BufferedInputStream(view.getContext().getAssets().open("empty_favicon.ico")));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    

    请注意,我们的代码中不能关闭 InputStream,因为它随后会被 WebView 用来读取图标。 WebviewClient 必须通过其设置器设置为 WebView:

    mWebView.setWebViewClient(subclassedWebViewClient);
    

    【讨论】:

    • 非常有帮助,为我工作。如果您不需要支持棒棒糖之前的设备,那么WebResourceResponse 可以传达 404 状态并且您不需要虚拟图标(或异常处理)。
    • 你可以返回 new WebResourceResponse("image/png", null, null);
    • 我认为我们不应该要求将图标放入资产并进行破解,而是我们可以传递 null 以进行响应并执行下一个过程。
    【解决方案3】:

    这是 Kotlin 的答案

    override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
        return if (request?.url?.lastPathSegment == "favicon.ico") {
            WebResourceResponse("image/png", null, null)
        } else {
            super.shouldInterceptRequest(view, request)
        }
    }
    

    默认情况下,Android Studio 生成代码时返回类型不可为空WebResourceResponse,但它不起作用所以将返回类型更改为可空WebResourceResponse

    【讨论】:

      【解决方案4】:

      您可以简单地将一些虚拟 InputStream 传递给 WebResourceResponse,如下所示。

      my_webview.webViewClient = object : WebViewClient() {
          override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
              if (request?.url?.toString()?.toLowerCase()?.endsWith("/favicon.ico") == true) {
                  val inputStream = "".byteInputStream(Charset.defaultCharset())
                  return WebResourceResponse("text", "UTF-8", inputStream)
              } else {
                  return super.shouldInterceptRequest(view, request)
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        WebView 类有一个名为 getFavicon() 的方法。我认为 WebView 调用该方法以通过发出请求从服务器检索网站图标。因此,您可以尝试扩展 WebView 类并覆盖 getFavicon() 方法以不执行任何操作。我自己没有尝试过,但这可能会奏效。

        【讨论】:

        • 这个不行,方法是同步的,只返回当前缓存的favicon的Bitmap。
        猜你喜欢
        • 2018-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-05
        • 1970-01-01
        • 2017-09-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多