Intercept all requests in WebView and replace URL example in Android environment
- 2021-12-04 19:53:08
- OfStack
Requirement background
To receive such a demand, it is necessary to add a flag bit of xxx=1 to all network requests of WebView in the requested url.
For example, http://www.baidu.com with the flag bit becomes http://www.baidu.com? xxx=1
Find a solution
Beginning with Android API 11 (3.0), WebView began to provide one API within WebViewClient, as follows:
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
That is to say, just implement the shouldInterceptRequest method of WebViewClient and then call setWebViewClient of WebView.
However, above API21, the above API was abandoned and a new API was used, as follows:
public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request)
Well, in order to support as many versions as possible, it seems that both need to be implemented, and it turns out that String url, which is very easy to use at first sight, has become an WebResourceRequest request. WebResourceRequest is an interface and is defined as follows:
public interface WebResourceRequest {
Uri getUrl();
boolean isForMainFrame();
boolean hasGesture();
String getMethod();
Map<String, String> getRequestHeaders();
}
There is no way to directly replace the request.
Then I searched for a reference to him in Android code, and click me to search. Then it is found that the internal implementation of private static class WebResourceRequestImpl implements WebResourceRequest is only a simple entity. Then it is very easy to replace this thing. You can do it in three ways:
Dynamic agent Reflex RealizationRealization
The plan is determined, and the rest is simple. Go directly to the code.
The first is the method of adding that flag bit to the URL string
public static String injectIsParams(String url) {
if (url != null && !url.contains("xxx=") {
if (url.contains("?")) {
return url + "&xxx=1";
} else {
return url + "?xxx=1";
}
} else {
return url;
}
}
Then you have to intercept all requests
webView.setWebViewClient(new WebViewClient() {
@SuppressLint("NewApi")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request) {
if (request != null && request.getUrl() != null) {
String scheme = request.getUrl().getScheme().trim();
if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
return super.shouldInterceptRequest(view, new WebResourceRequest() {
@Override
public Uri getUrl() {
return Uri.parse(injectIsParams(request.getUrl().toString()));
}
@SuppressLint("NewApi")
@Override
public boolean isForMainFrame() {
return request.isForMainFrame();
}
@SuppressLint("NewApi")
@Override
public boolean hasGesture() {
return request.hasGesture();
}
@SuppressLint("NewApi")
@Override
public String getMethod() {
return request.getMethod();
}
@SuppressLint("NewApi")
@Override
public Map<String, String> getRequestHeaders() {
return request.getRequestHeaders();
}
});
}
}
return super.shouldInterceptRequest(view, request);
}
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (!TextUtils.isEmpty(url) && Uri.parse(url).getScheme() != null) {
String scheme = Uri.parse(url).getScheme().trim();
if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) {
return super.shouldInterceptRequest(view, injectIsParams(url));
}
}
return super.shouldInterceptRequest(view, url);
}
});
You're done.
Welcome to point out the problems in the code ~ ~ 1 learning progress
Note: Pay attention to protecting Scheme of URL, and filter http and https in the code.
Extension
The above API found that there are more ways to play, such as:
Replace WebResourceResponse and construct your own WebResourceResponse. For example, the following code replaces the network picture to be requested with the local file in 1 package.
WebResourceResponse response = null;
if (url.contains("logo")) {
try {
InputStream is = getAssets().open("test.png");
response = new WebResourceResponse("image/png", "UTF-8", is);
} catch (IOException e) {
e.printStackTrace();
}
}
return response;
WebResourceRequest interface is used in API 21 (5.0) and above, which can modify the requesting Header
@Override
public Map<String, String> getRequestHeaders() {
return request.getRequestHeaders();
}
GET requests and POST requests can be distinguished in API 21 (5.0) and above, and can be used in some cases when it is necessary to distinguish different kinds of AJAX requests.