Android webview处理404 500 断网 timeout页面的问题(by 星空武哥)
转载请标注原创地址:http://blog.****.net/lsyz0021/article/details/56677132
现在混合开发的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(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这是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); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
判断断网和链接超时
@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
- 5
- 6
- 7
- 8
- 9
方案二(不推荐) 通过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页面
完整代码和测试页面:
http://download.****.net/download/lsyz0021/9760751
拿出微信 扫码关注下面的微信订阅号,及时获取更多推送文章
转载请标注原创地址:http://blog.****.net/lsyz0021/article/details/56677132
现在混合开发的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(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这是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); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
判断断网和链接超时
@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
- 5
- 6
- 7
- 8
- 9
方案二(不推荐) 通过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页面
完整代码和测试页面:
http://download.****.net/download/lsyz0021/9760751