Get HTTP Status Code in Android WebView

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.

Answers


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.


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.


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

    }       

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.


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.


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.


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

Need Your Help

How to use python regex to replace using captured group?

python regex sed replace

Suppose I want to change the blue dog and blue cat wore blue hats to the gray dog and gray cat wore blue hats.

Greyscale Background Css Images

css image background cross-browser grayscale

I've searched a lot on the web but I cannot find a cross browser solution to fade a css backgrund image to greyscale and back.