可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm developing an Android app that loads a website in a WebView, but sometimes the website returns HTTP code 500.
My question is: is there any way to get the HTTP status code from a WebView with a listener or with another class??
I tried to implement an WebViewClient, but I couldn't get the HTTP status code which WebView received.
回答1:
It's not possible (as of the time i'm writing this). The docs for onReceiveError()
are ambiguous at best, but it you look at this issue,
http://code.google.com/p/android/issues/detail?id=968
It's clear that HTTP status codes won't be reported through that mechanism. How it's possible that the developers wrote WebView
with no way to retrieve the HTTP status code really blows my mind.
回答2:
You can load content with ajax and then just put it into the webview with loadDataWithBaseURL.
Create a web page like this
<script type="text/javascript">
function loadWithAjax() {
var httpRequest = new XMLHttpRequest();
var path = 'PATH';
var host = 'HOST';
var url = 'URL';
httpRequest.onreadystatechange = function(){
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
browserObject.onAjaxSuccess(host, url, httpRequest.responseText);
} else {
browserObject.onAjaxError(host, url, httpRequest.status);
}
}
};
httpRequest.open('GET', path, true);
httpRequest.send(null);
}
</script>
<body onload="loadWithAjax()">
browserObject is java object injected into javascript.
addJavascriptInterface(this, "browserObject");
And load it into webView. You should replace path/url with your values.
ajaxHtml = IOUtils.toString(getContext().getAssets().open("web/ajax.html"));
ajaxHtml = ajaxHtml.replace("PATH", path);
ajaxHtml = ajaxHtml.replace("URL", url);
ajaxHtml = ajaxHtml.replace("HOST", host);
loadDataWithBaseURL(host, ajaxHtmlFinal, "text/html", null, null);
Then handle onAjaxSuccess/onAjaxError like this:
public void onAjaxSuccess(final String host, final String url, final String html)
{
((Activity) getContext()).runOnUiThread(new Runnable()
{
@Override
public void run()
{
loadDataWithBaseURL(url, html, "text/html", null, null);
}
});
}
public void onAjaxError(final String host, final String url, final int errorCode)
{
}
Now you can handle http errors.
回答3:
Actually it's not too bad to check HTTP status to see if content is available to load into a webview. Assumed: You've already set your webview and you have the string for your target URL then...
AsyncTask<Void, Void, Void> checkURL = new AsyncTask<Void, Void, Void>() {
@Override
protected void onPreExecute() {
pd = new ProgressDialog(WebActivity.this, R.style.DickeysPDTheme);
pd.setTitle("");
pd.setMessage("Loading...");
pd.setCancelable(false);
pd.setIndeterminate(true);
pd.show();
}
@Override
protected Void doInBackground(Void... arg0) {
// TODO Auto-generated method stub
int iHTTPStatus;
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpRequest = new HttpGet(sTargetURL);
HttpResponse httpResponse = httpClient.execute(httpRequest);
iHTTPStatus = httpResponse.getStatusLine().getStatusCode();
if( iHTTPStatus != 200) {
// Serve a local page instead...
wv.loadUrl("file:///android_asset/index.html");
}
else {
wv.loadUrl(sTargetURL); // Status = 200 so we can loard our desired URL
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
// Show a toast for now...
Toast.makeText(WebActivity.this, "UNSUPPORTED ENCODING EXCEPTION", Toast.LENGTH_LONG).show();
} catch (ClientProtocolException e) {
e.printStackTrace();
// Show a toast for now...
Toast.makeText(WebActivity.this, "CLIENT PROTOCOL EXCEPTION", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
// Show a toast for now...
Toast.makeText(WebActivity.this, "I/O EXCEPTION", Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
// Show a toast for now...
Toast.makeText(WebActivity.this, "GENERIC EXCEPTION", Toast.LENGTH_LONG).show();
}
return null;
}
};
checkURL.execute((Void[])null);
Elsewhere, in WebViewClient, dismiss the progress dialog
@Override
public void onPageFinished(WebView view, String url)
{
// Do necessary things onPageFinished
if (pd!=null) {
pd.dismiss();
}
}
回答4:
It looks as though this is possible via a new callback in the Android M API (https://code.google.com/p/android/issues/detail?id=82069#c7).
void onReceivedHttpError(WebView view, WebResourceRequest request,
WebResourceResponse errorResponse)
Unfortunately, this will most likely not available in pre-Android M devices.
回答5:
At this time you cannot get normal HTTP response code.
But as solution, if is possible to you to modify webapp server side, to use following:
On the server create some JavaScript function, let's say, riseHttpError
.
On android side use JavaScript interface and when you need to tell android to handle http error, just call Android.riseHttpError()
on server.
Android will handles this function and you will be able to do required actions on android side.
In my solution were required to get errors. You can send any code you want. :)
Of course, this is just another variation how to do it. So, probably there is others, much better solutions.
But if you can modify server side, I think, this will be better to do double request using URLHandler
.
回答6:
I don't think it is possible to get status code in easy way(if it's at all possible) from webView.
My idea is to use onReceivedError() method from WebViewClient(as you said) with defined errors in WebViewClient (full list of errors is available here: http://developer.android.com/reference/android/webkit/WebViewClient.html) and assume that for instance 504 status code is equals to WebViewClient.ERROR_TIMEOUT etc.
回答7:
You should use this after the on Page finished
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error){
//Your code to do
Toast.makeText(
getActivity(),
"Your Internet Connection May not be active Or " + error,
Toast.LENGTH_LONG
).show();
}