轉載請標注原創(chuàng)地址:
現(xiàn)在混合開發(fā)的app越來越多,Google對webview也越來越重視,在早期的版本webview有很多的bug,例如404、500等請求錯誤碼我們無發(fā)直接獲?。ㄟ@個bug早在2008年就有人提交過issue給Google),好在Google在Android6.0修復了這個問題。根據(jù)google官網(wǎng)提供的最新的官網(wǎng)文檔,我們可以重寫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才出現(xiàn)
int statusCode = errorResponse.getStatusCode();
}
這是google關于這個issue的:</br>
https://code.google.com/p/android/issues/detail?id=968
下面是google開發(fā)人員回復:

Google雖然在Android6.0解決了這個問題,但是Android6.0以下的手機市場占有率還是很多的,所以我們就要自己手動去解決這個問題。
處理404、500
在Android6.0以下我們是不能直接獲取到404或者500的,Android6.0谷歌解決了這個問題。那么在Android6.0以下的系統(tǒng)我們如何處理404這樣的問題呢?
兩種解決方案:
方案一(推薦)通過獲取網(wǎng)頁的title,判斷是否為系統(tǒng)默認的404頁面
我們可以在WebChromeClient()子類中可以重寫他的onReceivedTitle()方法</br>
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");// 避免出現(xiàn)默認的錯誤界面
view.loadUrl(mErrorUrl);
}
}
}
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才出現(xiàn)
int statusCode = errorResponse.getStatusCode();
System.out.println("onReceivedHttpError code = " + statusCode);
if (404 == statusCode || 500 == statusCode) {
view.loadUrl("about:blank");// 避免出現(xiàn)默認的錯誤界面
view.loadUrl(mErrorUrl);
}
}
判斷斷網(wǎng)和鏈接超時
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
// 斷網(wǎng)或者網(wǎng)絡連接超時
if (errorCode == ERROR_HOST_LOOKUP || errorCode == ERROR_CONNECT || errorCode == ERROR_TIMEOUT) {
view.loadUrl("about:blank"); // 避免出現(xiàn)默認的錯誤界面
view.loadUrl(mErrorUrl);
}
}
方案二(極力不推薦) 通過HttpURLConnection請求url獲取狀態(tài)碼
在webview加載url前先通過HttpURLConnection獲取請求碼,這種方案有時候不會觸發(fā)shouldOverrideUrlLoading()方法,但是網(wǎng)上還有很多的呼聲。
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;
}
}
HttpURLConnection獲取請求狀態(tài)碼
/**
* 獲取請求狀態(tài)碼
*
* @param url
* @return 請求狀態(tài)碼
*/
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;
}
方案三(推薦) 服務器后臺是能獲取404、500的,最好的辦法是讓后臺捕獲
這里就不說了
測試用的500的test.jsp頁面

完整代碼和測試頁面: