Reputation: 20410
In order to access response headers (get specific header value) we have to intercept HTTP requests in WebView, perform the downloading of HTTP resources by ourselves and return a result as a WebResourceResponse
instance:
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
{
return new WebResourceResponse("text/plain", "UTF-8", 302, ...); // 302 is invalid (not supported) value
}
However the codes within 300-399 are not accepted:
2019-12-02 16:48:05.710 1812-1903 W/System.err: java.lang.IllegalArgumentException: statusCode can't be in the [300, 399] range.
2019-12-02 16:48:05.712 1812-1903 W/System.err: at android.webkit.WebResourceResponse.setStatusCodeAndReasonPhrase(WebResourceResponse.java:134)
2019-12-02 16:48:05.712 1812-1903 W/System.err: at android.webkit.WebResourceResponse.<init>(WebResourceResponse.java:76)
...
2019-12-02 16:48:05.714 1812-1903 W/System.err: at xl.a(PG:56)
2019-12-02 16:48:05.714 1812-1903 W/System.err: at aeW.a(PG:9)
2019-12-02 16:48:05.714 1812-1903 W/System.err: at org.chromium.android_webview.AwContentsBackgroundThreadClient.shouldInterceptRequestFromNative(PG:11)
2019-12-02 16:48:05.718 1812-1903 A/chromium: [FATAL:jni_android.cc(256)] Please include Java exception stack in crash report
Is there any proper way to make WebView accept the redirect response?
PS. I was able to workaround it with Java reflection and inject the values right into the fields (not via ctor with validation), but it seems to be extremely fragile (though it worked in fact).
Upvotes: 3
Views: 4034
Reputation: 91
As OP stated, they were able to work around this restriction by using reflection. The other answer was insufficient for my needs, so I also took the approach of reflection.
// instantiate a response with a default 200 response code
WebResourceResponse redirectResponse = new WebResourceResponse("text/html", "utf-8", 200, new ByteArrayInputStream(content.getBytes()));
// use reflection to set the actual response code
Field f = WebResourceResponse.class.getDeclaredField("mStatusCode");
f.setAccessible(true);
f.setInt(redirectResponse, 302);
return redirectResponse;
Upvotes: 3
Reputation: 91
I encountered the same problem.
Solution 1: load new url
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String statusCode = 302; //get it from your response;
if (statusCode >= 300 && statusCode <= 399) {
final String newUrl = "https://example.com";
final myWebview = view;
view.post(new Runnable() {
@Override public void run() {
myWebview.loadUrl(newUrl);
}
});
WebResourceResponse nullRes = new WebResourceResponse("text/html", "utf-8", new ByteArrayInputStream("".getBytes()));
return nullRes;
}
}
Solution 2: return an html template
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String statusCode = 302; //get it from your response;
if (statusCode >= 300 && statusCode <= 399) {
String newUrl = "https://example.com";
String content = "<script>location.href = '" + newUrl + "'</script>";
WebResourceResponse redirectRes = new WebResourceResponse("text/html", "utf-8", new ByteArrayInputStream(content.getBytes()));
return redirectRes;
}
}
Upvotes: 6