Android WebViewClient url redirection (Android URL

2019-04-15 09:23发布

I was trying intercept webview request using: ShouldInterceptRequest, inside it I used HttpUrlConnection to fetch data from server, I set it to follow the redirection, which is transparent to webviewclient. This means when I return WebResponseResource("", "", data_inputstream), webview maynot know the target host was changed. How can I tell the webview this happened?

ourBrowser.setWebViewClient(new WebViewClient() {
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view,
                String url) {
                    ..... //some code omitted here

                HttpURLConnection conn = null;
                try {
                    conn = (HttpURLConnection) newUrl.openConnection();
                    conn.setFollowRedirects(true);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                   ..... //

                InputStream is = null;
                try {
                    is = conn.getInputStream();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return new WebResourceResponse(mimeType, encoding, is);

            }
        }

If I request "google.com", it should be redirected to "google.co.uk", but webview didnt know the redirection, if the link of css file attaching with "co.uk" is "/render/something.css", the webview still go to "http://www.google.com/render/something.css" to find the css file which should be "http://www.google.co.uk/render/something.css".

Anyone can help me?

2条回答
贪生不怕死
2楼-- · 2019-04-15 09:50

You can enable HTTP redirects globally for all the HttpURLConnection objects:

HttpURLConnection.setFollowRedirects(true);

then in the shouldInterceptRequest() method you check for the connection response code:

public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
  ...
  int respCode = conn.getResponseCode();
  if( respCode >= 300 && respCode < 400 ) {
    // redirect
    return null;
  } else if( respCode >= 200 && respCode < 300 ) {
    // normal processing
    ...
}

The Android framework should call shouldInterceptRequest() again with the new URL which is the redirection target, and this time the connection response code will be 2xx.

查看更多
beautiful°
3楼-- · 2019-04-15 10:06

Certain metadata (url, headers, etc..) can't be specified by the WebResourceResponse class. That means that you can only use shouldInterceptRequest to supply different data (change the page's content) but you can't use it to change the URL it's being loaded at.

In your case you're consuming the redirect within the HttpUrlConnection, so the WebView is still thinking that it's loading "http://www.google.com/" (even if the content is coming from "http://google.co.uk/"). If Google's home page doesn't explicitly set a base URL the WebView will continue to assume the base URL is "http://www.google.com/" (since it hasn't seen the redirect). Since relative resource references (like <link href="//render/something.css" />) are resolved against the baseURL (which in this case is "http://www.google.com/" and not "http://www.google.co.uk/") you get the result you observed.

What you could do is use HttpUrlConnection to figure out whether the URL you're going to load is a redirect and return null in that case. However I would strongly advise against using HttpUrlConnection from shouldInterceptRequest in general - the WebView's network stack is much more efficient and will perform fetches in parallel (whereas using shouldInterceptRequest will serialize all of the loads in pre-KK WebViews).

查看更多
登录 后发表回答