在Android WebView中获取HTTP状态代码

时间:2012-08-09 17:42:37

标签: android http android-webview

我正在开发一个在WebView中加载网站的Android应用,但有时网站会返回HTTP代码500.

我的问题是:有没有办法从带有监听器或其他类的WebView获取HTTP状态代码?

我尝试实现WebViewClient,但是我无法获取WebView收到的HTTP状态代码。

8 个答案:

答案 0 :(得分:15)

这是不可能的(截至我写这篇文章的时候)。 onReceiveError()的文档充其量是模棱两可的,但是你看看这个问题,

  

http://code.google.com/p/android/issues/detail?id=968

很明显,不会通过该机制报告HTTP状态代码。开发人员编写WebView而无法检索HTTP状态代码的可能性真的让我大吃一惊。

答案 1 :(得分:12)

您可以使用ajax加载内容,然后使用loadDataWithBaseURL将其放入webview中。

像这样创建一个网页

<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错误。

答案 2 :(得分:3)

实际上,检查HTTP状态以查看内容是否可用于加载到webview中并不算太糟糕。假设:您已经设置了webview,并且您拥有目标网址的字符串,然后......

    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);

在其他地方,在WebViewClient中,关闭进度对话框

@Override  
    public void onPageFinished(WebView view, String url)  
    {
        // Do necessary things onPageFinished
        if (pd!=null) {
            pd.dismiss();
        }

    }       

答案 3 :(得分:3)

看起来这可以通过Android M API(https://code.google.com/p/android/issues/detail?id=82069#c7)中的新回调实现。

  

void onReceivedHttpError(WebView视图,WebResourceRequest请求,   WebResourceResponse errorResponse)

不幸的是,这很可能在Android M之前的设备中无法使用。

答案 4 :(得分:3)

您可以重写onReceivedHttpError方法,在那里您可以看到状态代码:

@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
    super.onReceivedHttpError(view, request, errorResponse);
    int statusCode = errorResponse.getStatusCode();
    // TODO: dou your logic..
}

答案 5 :(得分:2)

此时您无法获得正常的 HTTP 响应代码。

但作为解决方案,如果可以修改webapp服务器端,请使用以下命令:

在服务器上创建一些 JavaScript 功能,比方说,riseHttpError

在android端使用 JavaScript 界面,当你需要告诉android处理http错误时,只需在服务器上调用Android.riseHttpError()

Android将处理此功能,您将能够在android端执行必要的操作。

在我的解决方案中需要出错。您可以发送任何您想要的代码。 :)

当然,这只是另一种变化方法。所以,可能还有其他更好的解决方案。

但是,如果您可以修改服务器端,我认为,使用URLHandler进行双重请求会更好。

答案 6 :(得分:1)

我认为不可能从webView轻松获取状态代码(如果可能的话)。

我的想法是使用WebViewClient中的onReceivedError()方法(如你所说)和WebViewClient中定义的错误(完整的错误列表在这里:http://developer.android.com/reference/android/webkit/WebViewClient.html)并假设例如504状态代码等于WebViewClient.ERROR_TIMEOUT等。

答案 7 :(得分:-1)

你应该在页面完成后使用它

@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();
}