web-dev-qa-db-fra.com

Obtenez le code d'état HTTP dans Android WebView

Je développe une Android qui charge un site Web dans une WebView, mais parfois le site Web renvoie le code HTTP 500.

Ma question est: existe-t-il un moyen d'obtenir le code d'état HTTP à partir d'une WebView avec un écouteur ou avec une autre classe ??

J'ai essayé d'implémenter un WebViewClient, mais je n'ai pas pu obtenir le code d'état HTTP que WebView a reçu.

29
Victor Escobar

Ce n'est pas possible (au moment où j'écris ceci). Les documents pour onReceiveError() sont au mieux ambigus, mais si vous regardez ce problème,

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

Il est clair que les codes d'état HTTP ne seront pas signalés via ce mécanisme. Comment il est possible que les développeurs aient écrit WebView sans aucun moyen de récupérer le code de statut HTTP me fait vraiment peur.

16
Jeffrey Blattman

Vous pouvez charger du contenu avec ajax, puis simplement le mettre dans la vue Web avec loadDataWithBaseURL.

Créez une page Web comme celle-ci

<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 est Java objet injecté en javascript.

addJavascriptInterface(this, "browserObject");

Et chargez-le dans webView. Vous devez remplacer path/url par vos valeurs.

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

Ensuite, gérez onAjaxSuccess/onAjaxError comme ceci:

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

    }

Vous pouvez maintenant gérer les erreurs http.

13
Alexander Ponomarev

Il semble que cela soit possible via un nouveau rappel dans l'API Android M ( https://code.google.com/p/Android/issues/detail?id= 82069 # c7 ).

void onReceivedHttpError (vue WebView, demande WebResourceRequest, WebResourceResponse errorResponse)

Malheureusement, cela ne sera probablement pas disponible sur les appareils pré-Android M.

3
Jose Gómez

En fait, il n'est pas trop mal de vérifier l'état HTTP pour voir si le contenu est disponible pour être chargé dans une vue Web. Supposé: vous avez déjà défini votre vue Web et vous disposez de la chaîne de votre URL cible, puis ...

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

Ailleurs, dans WebViewClient, fermez la boîte de dialogue de progression

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

    }       
3
gman413

Pour le moment, vous ne pouvez pas obtenir un code de réponse normal HTTP .

Mais comme solution, s'il vous est possible de modifier côté serveur webapp, utilisez ce qui suit:

Sur le serveur, créez une fonction JavaScript, disons, riseHttpError.

Sur Android side use JavaScript interface et quand vous devez dire Android pour gérer l'erreur http, il suffit d'appeler Android.riseHttpError() sur le serveur.

Android gère cette fonction et vous pourrez effectuer les actions requises du côté Android côté.

Dans ma solution, il fallait obtenir des erreurs. Vous pouvez envoyer le code de votre choix. :)

Bien sûr, ce n'est qu'une autre variante de la façon de le faire. Il y a donc probablement d'autres solutions bien meilleures.

Mais si vous pouvez modifier le côté serveur, je pense que ce sera mieux de faire une double requête en utilisant URLHandler.

2
Ken Shiro

Je ne pense pas qu'il soit possible d'obtenir le code d'état de manière simple (si c'est possible) à partir de webView.

Mon idée est d'utiliser la méthode onReceivedError () de WebViewClient (comme vous l'avez dit) avec des erreurs définies dans WebViewClient (la liste complète des erreurs est disponible ici: http://developer.Android.com/reference/Android/webkit/ WebViewClient.html ) et supposons que, par exemple, le code d'état 504 est égal à WebViewClient.ERROR_TIMEOUT etc.

1
Mike

Vous pouvez remplacer la méthode onReceivedHttpError et là vous pouvez voir le code d'état:

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