现在混合开发的app越来越多,Google对webview也越来越重视,在早期的版本webview有很多的bug,例如404、500等请求错误码我们无发直接获取(这个bug早在2008年就有人提交过issue给Google),好在Google在Android6.0修复了这个问题。根据google官网提供的最新的官网文档,我们可以重写onReceivedHttpError()方法可以捕获http Error。
@TargetApi(android.os.Build.VERSION_CODES.M)
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
// 这个方法在6.0才出现
int statusCode = errorResponse.getStatusCode();
}
这是google关于这个issue的:
https://code.google.com/p/android/issues/detail?id=968
下面是google开发人员回复:
Google虽然在Android6.0解决了这个问题,但是Android6.0以下的手机市场占有率还是很多的,所以我们就要自己手动去解决这个问题。
处理404、500
在Android6.0以下我们是不能直接获取到404或者500的,Android6.0谷歌解决了这个问题。那么在Android6.0以下的系统我们如何处理404这样的问题呢?
两种解决方案:
方案一(推荐)通过获取网页的title,判断是否为系统默认的404页面
我们可以在WebChromeClient()子类中可以重写他的onReceivedTitle()方法
Android6.0以下判断404或者500:
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
// android 6.0 以下通过title获取
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (title.contains("404") || title.contains("500") || title.contains("Error")) {
view.loadUrl("about:blank");// 避免出现默认的错误界面
view.loadUrl(mErrorUrl);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
Android6.0以上判断404或者500:
@TargetApi(android.os.Build.VERSION_CODES.M)
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
// 这个方法在6.0才出现
int statusCode = errorResponse.getStatusCode();
System.out.println("onReceivedHttpError code = " + statusCode);
if (404 == statusCode || 500 == statusCode) {
view.loadUrl("about:blank");// 避免出现默认的错误界面
view.loadUrl(mErrorUrl);
}
}
判断断网和链接超时
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
// 断网或者网络连接超时
if (errorCode == ERROR_HOST_LOOKUP || errorCode == ERROR_CONNECT || errorCode == ERROR_TIMEOUT) {
view.loadUrl("about:blank"); // 避免出现默认的错误界面
view.loadUrl(mErrorUrl);
}
}
1
2
3
4
方案二(不推荐) 通过HttpURLConnection请求url获取状态码
在webview加载url前先通过HttpURLConnection获取请求码,这种方案有时候不会触发shouldOverrideUrlLoading()方法,但是网上还有很多的呼声。
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int code = msg.what;
if (code == 404 || code == 500) {
System.out.println("handler = " + code);
mWebView.loadUrl(mErrorUrl);
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
int responseCode = getResponseCode(mUrl);
if (responseCode == 404 || responseCode == 500) {
Message message = mHandler.obtainMessage();
message.what = responseCode;
mHandler.sendMessage(message);
}
}
}).start();
mWebView.loadUrl(mUrl);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
new Thread(new Runnable() {
@Override
public void run() {
int responseCode = getResponseCode(mUrl);
if (responseCode == 404 || responseCode == 500) {
Message message = mHandler.obtainMessage();
message.what = responseCode;
mHandler.sendMessage(message);
}
}
}).start();
view.loadUrl(url);
return true;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
HttpURLConnection获取请求状态码
/**
* 获取请求状态码
*
* @param url
* @return 请求状态码
*/
private int getResponseCode(String url) {
try {
URL getUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(5000);
connection.setConnectTimeout(5000);
return connection.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
}
return -1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
方案三(推荐) 服务器后台是能获取404、500的,最好的办法是让后台捕获
这里就不说了
测试用的500的test.jsp页面