为什么WebViewClient.shouldInterceptRequest在4.4之后不支持重定向?

时间:2017-10-08 22:06:49

标签: android webview network-programming android-webview url-redirection

我试图拦截进出主机应用程序内WebView的所有网络通信。我的尝试集中在WebViewClient提供的两个shouldInterceptRequest方法:

@Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
    Log.d(Constants.Tags.WEBVIEW_CLIENT, "WV REQUEST (OLD) " + url);
    return processRequest(url);
}

@Override
@TargetApi(21)
public WebResourceResponse shouldInterceptRequest(final WebView view, WebResourceRequest
        interceptedRequest) {
    Log.d(Constants.Tags.WEBVIEW_CLIENT, "WV REQUEST (NEW) " + interceptedRequest.getUrl
            ().toString() + " " + interceptedRequest.getMethod());
    return processRequest(interceptedRequest);
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private WebResourceResponse processRequest(WebResourceRequest ir) {
    if (!"GET".equals(ir.getMethod())) {
        Log.d(Constants.Tags.WEBVIEW_CLIENT, "IGNORING " + ir.getMethod() + " " + ir.getUrl());
        return null;
    }
    return processRequest(ir.getUrl().toString());
}

private WebResourceResponse processRequest(String url) {
    Request request = new Request.Builder().url(url).build();
    try {
        return processResponse(okHttpClient.newCall(request).execute());
    } catch (SSLHandshakeException e) {
        Log.d(Constants.Tags.WEBVIEW_CLIENT, "SSLHandshakeException: " + e.getMessage());
    } catch (IOException e) {
        Log.d(Constants.Tags.WEBVIEW_CLIENT, "IOException: " + e.getMessage());
        e.printStackTrace();
    }
    return null;
}

private WebResourceResponse processResponse(Response response) {
    String contentType = response.body().contentType().toString();

    if (contentType != null) {
        String mimeType = contentType;

        if (contentType.contains(";")) {
            mimeType = contentType.split(";")[0].trim();
        }

        WebResourceResponse webResourceResponse = new WebResourceResponse(mimeType, response
                .header("content-encoding", "utf-8")
                , response.body().byteStream());

        if (Build.VERSION.SDK_INT > 21) {
            webResourceResponse.setResponseHeaders(convertHeaders(response.headers()));
            webResourceResponse.setStatusCodeAndReasonPhrase(response.code(),"whatever");
        }

        return webResourceResponse;
    }
    return null;
}

private Map<String, String> convertHeaders(Headers headers) {
    Map<String, String> map = new HashMap<>();
    for (int i = 0; i < headers.size(); i++) {
        map.put(headers.name(i), headers.value(i));
    }
    return map;
}

为了使这个成为可行的解决方案,我试图将所有标头和响应代码附加到API级别21或更高级别的WebResourceResponse对象上。 我认为这是不可能做到的原因之一,即使我跳过除GET请求之外的任何事情都是不支持拦截重定向的事实。这两种方式都是有效的:应用程序 - &gt; Webview和WebView - &gt;应用。

摘自WebResourceResponse的文档,关于setStatusCodeAndReasonPhrase中状态代码参数的值:

  

int:状态代码需要在[100,299],[400,599]范围内。   不支持通过指定3xx代码导致重定向。

我设法通过绕过带有反射的受监视的setter来获取响应代码302以在Lollipop或更新的浏览器上工作。这仅对应用程序有效 - &gt; WebView,因为WebView不会向WebViewClient确认它正在执行重定向请求(在我传回hacky 302 WebResourceResponse之后的下一步)。只是没有为该请求调用shouldInterceptRequest。

我不打算用最初的意图打扰任何人。我只是想知道为什么现代WebView不支持重定向?到目前为止,我正在得出的结论是,原因是与4.4之前的WebView提供程序兼容(可能不是基于Chromium的)。但是,这没有多大意义:我根本无法在5.0以下的Android版本上调用setStatusCodeAndReasonPhrase。

非常感谢任何反馈。

0 个答案:

没有答案