我正在开发一个Android应用,其中一个WebView会加载一个网站,但有时候该网站会返回HTTP代码500。
我的问题是:是否有办法通过监听器或其他类从WebView中获取HTTP状态码?
我尝试了实现一个WebViewClient,但无法获取WebView接收到的HTTP状态码。
我正在开发一个Android应用,其中一个WebView会加载一个网站,但有时候该网站会返回HTTP代码500。
我的问题是:是否有办法通过监听器或其他类从WebView中获取HTTP状态码?
我尝试了实现一个WebViewClient,但无法获取WebView接收到的HTTP状态码。
目前(我写这篇文章的时候)似乎不可能实现。对于onReceiveError()
的文档至多也只是模糊的解释,但如果你看一下这个问题:
很明显,HTTP状态码不能通过这种机制来报告。如何可能开发人员编写WebView
却没有任何方法来检索HTTP状态码,这真的让我感到难以置信。
您可以使用ajax加载内容,然后将其放入webview中使用loadDataWithBaseURL。
创建一个像这样的网页
<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 是注入到 JavaScript 中的 Java 对象。
addJavascriptInterface(this, "browserObject");
将其加载到webView中。您应该使用您的值替换路径/网址。
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);
然后像这样处理onAjaxSuccess/onAjaxError:
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)
{
}
现在你可以处理http错误。
loadWithAjax()
放在哪里呢?谢谢。 - Regex RookieWebViewClient
的onReceivedHttpError
方法,在那里你可以看到状态码:@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
int statusCode = errorResponse.getStatusCode();
// TODO: do your logic..
}
看起来可以通过 Android M API 中的新回调函数实现此功能(https://code.google.com/p/android/issues/detail?id=82069#c7)。
void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse)
不幸的是,这很可能不适用于 Android M 之前的设备。
实际上,检查HTTP状态以查看内容是否可加载到Web视图中并不太难。假定:您已经设置了Web视图,并且具有目标URL的字符串,则...
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);
@Override
public void onPageFinished(WebView view, String url)
{
// Do necessary things onPageFinished
if (pd!=null) {
pd.dismiss();
}
}
目前您无法获得正常的HTTP响应代码。
但是,如果您可以修改Web应用程序服务器端,请使用以下方法:
在服务器上创建一些JavaScript函数,例如riseHttpError
。
在Android端使用JavaScript接口,当您需要告诉Android处理HTTP错误时,只需在服务器上调用Android.riseHttpError()
。
Android将处理此函数,并且您将能够在Android端执行所需操作。
在我的解决方案中需要获取错误。您可以发送任何想要的代码。 :)
当然,这只是另一种变化方式。因此,可能存在其他更好的解决方案。
但是,如果您可以修改服务器端,我认为最好使用URLHandler
进行双重请求。
我认为从webView中以简单的方式(如果有可能的话)获取状态码是不可能的。
我的想法是使用WebViewClient的onReceivedError()方法(正如你所说),并在WebViewClient中定义错误(完整的错误列表可在此处找到:http://developer.android.com/reference/android/webkit/WebViewClient.html),并假设例如504状态码等于WebViewClient.ERROR_TIMEOUT等。
实现简单Activity的完整示例
适用于API Level >= 23
Java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView myWebView = (WebView)findViewById(R.id.webview);
myWebView.loadUrl("https://www.fñdghd.es");
myWebView.setWebViewClient(new CustomWebViewClient());
}
private class CustomWebViewClient extends WebViewClient
{
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)
{
super.onReceivedError(view, request, error);
Log.e("MainActivity",(String) error.getDescription());
Log.e("MainActivity",String.valueOf(error.getErrorCode()));
//Todo: Something to define.
}
}
}
C# 适用于 Xamarin 或 Maui
public class WebViewActivity : Activity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_webview);
WebView myWebView = (WebView)FindViewById(Resource.Id.webview);
myWebView.LoadUrl("https://www.google.es");
myWebView.SetWebViewClient(new CustomWebViewClient());
}
}
internal class CustomWebViewClient : WebViewClient
{
public override void OnReceivedError(WebView view, IWebResourceRequest request, WebResourceError error)
{
base.OnReceivedError(view, request, error);
Console.WriteLine(error.Description);
Console.WriteLine(error.ErrorCode);
//Todo: Something to define.
}
}
在页面完成后,您应该使用此功能。
@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();
}