注意:由于 shouldInterceptRequest(WebView view, WebResourceRequest request) 中 WebResourceRequest 没有提供请求 body 信息,所以只能成功拦截 get 请求,无法拦截 post 请求。
WebSettings webSettings = mWebView.getSettings();// 使用默认的缓存策略,cache 没有过期就用 cachewebSettings.setCacheMode(WebSettings.LOAD_DEFAULT);// 加载网页图片资源webSettings.setBlockNetworkImage(false);// 支持 JavaScript 脚本webSettings.setJavaScriptEnabled(true);// 支持缩放webSettings.setSupportZoom(true);mWebView.setWebViewClient(new WebViewClient() { // API 21及之后使用此方法 @SuppressLint("NewApi") @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { if (request != null && request.getUrl() != null && request.getMethod().equalsIgnoreCase("get")) { String scheme = request.getUrl().getScheme().trim(); String url = request.getUrl().toString(); Log.d(TAG, "url:" + url); if (scheme.equalsIgnoreCase("http") || scheme.equalsIgnoreCase("https")) { try { URL oldUrl = new URL(url); URLConnection connection = oldUrl.openConnection(); // 获取 HTTPDNS 域名解析结果 String ips = MSDKDnsResolver.getInstance().getAddrByName(oldUrl.getHost()); String[] ipArr = ips.split(";"); if (2 == ipArr.length && !"0".equals(ipArr[0])) { // 通过 HTTPDNS 获取 IP 成功,进行 URL 替换和 HOST 头设置 String ip = ipArr[0]; String newUrl = url.replaceFirst(oldUrl.getHost(), ip); connection = (HttpURLConnection) new URL(newUrl).openConnection(); // 设置 HTTP 请求头 Host 域名 connection.setRequestProperty("Host", oldUrl.getHost()); } String contentType = connection.getContentType(); Log.d(TAG, "contentType:" + connection.getContentType()); if (contentType != null) { String mimeType = contentType.split(";")[0]; // encoding 可从 contentType 中获取,demo 中不展开处理 String encoding = "UTF-8"; return new WebResourceResponse(mimeType, encoding, connection.getInputStream()); } return null; } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } return null; } // API < 21时,shouldInterceptRequest(WebView view, String url) 仅能获取 URL,无法获取请求方法、头部信息等,拦截请求可能无法获取正确响应。放弃拦截。 @Override public WebResourceResponse shouldInterceptRequest(WebView view, String url) { return null; }}); // 加载web资源mWebView.loadUrl(targetUrl);
若拦截资源返回重定向:
·需发起二次请求;
·原请求资源中存在cookie时,需进行cookie管理,获取请求cookie重新写入redirect请求。
cookieManager.removeAllCookies(null);// Cookie获取List<String> cookies = conn.getHeaderFields().get("Set-Cookie");if (cookies != null) { for (String cookieStr: cookies) { if (!TextUtils.isEmpty(cookieStr)) { // cookie值若带domain,需与url一致才能写入成功 cookieManager.setCookie(url, cookieStr.split(";")[0]); } }}if (needRedirect(code)) { String location = conn.getHeaderField("Location");
if (location == null) { location = conn.getHeaderField("location");
}
if (location != null) {
if (!(location.startsWith("http://") || location.startsWith("https://"))) {
// 补全重定向完整url
URL originalUrl = new URL(url);
location = originalUrl.getProtocol() + "://"
+ originalUrl.getHost() + location;
}
Log.e(TAG, "location: " + location + "; path: " + path); // 发起二次请求 // Cookie写入 conn.setRequestProperty("Cookie", cookieManager.getCookie(location)); … } else { // 无法获取location信息,放弃拦截 return null;
}
} else {
Log.e(TAG, "redirect finish");
…
}
注意:拦截 HTTPS 请求中涉及证书校验与 SNI 问题处理,请参见 HttpURLConnection 接入。