web-dev-qa-db-fra.com

Android: Comment gérer une erreur de message du serveur utilisant Volley?

J'utilise Volley pour mon Android) pour récupérer les données de mon serveur. Cela fonctionne bien, sauf lorsque l'erreur est traitée sur mon serveur. Mon serveur envoie cette réponse lorsqu'il est une erreur:

{
    "status": 400,
    "message": "Errors (2): A name is required- Julien is already used. Not creating."
}

Mon but est d’obtenir le message puis de l’afficher dans un Toast. J'ai suivi quelques exemples pour savoir comment faire cela, mais cela ne fonctionne pas.

Il y a mon écouteur d'erreur:

public void onErrorResponse(VolleyError error) {
            int  statusCode = error.networkResponse.statusCode;
            NetworkResponse response = error.networkResponse;

            Log.d("testerror",""+statusCode+" "+response.data);
            // Handle your error types accordingly.For Timeout & No connection error, you can show 'retry' button.
            // For AuthFailure, you can re login with user credentials.
            // For ClientError, 400 & 401, Errors happening on client side when sending api request.
            // In this case you can check how client is forming the api and debug accordingly.
            // For ServerError 5xx, you can do retry or handle accordingly.
            if( error instanceof NetworkError) {
            } else if( error instanceof ClientError) {
            } else if( error instanceof ServerError) {
            } else if( error instanceof AuthFailureError) {
            } else if( error instanceof ParseError) {
            } else if( error instanceof NoConnectionError) {
            } else if( error instanceof TimeoutError) {
            }
            showProgress(false);
            mPasswordView.setError(getString(R.string.error_incorrect_password));
            mPasswordView.requestFocus();

        }

Et là le résultat de mon débogueur: testerror ﹕ 400 [B @ 430b8d60

EDIT: De plus mon error.getMessage () est null.

Je ne comprends donc pas pourquoi ma variable response.data n'est pas la réponse de mon serveur.

Si quelqu'un sait comment je peux obtenir le message de mon serveur, ce sera cool.

Merci,

70
FlavienBert

J'ai mis en place quelque chose de similaire à cela, et c'est relativement simple. Votre message de journal imprime ce qui ressemble à du charabia, car response.data Est vraiment un tableau d'octets - pas un String. De plus, un VolleyError n'est en réalité qu'un Exception étendu, donc Exception . GetMessage () ne renverra probablement pas ce que vous recherchez, sauf si vous écrasez les méthodes d'analyse pour analyser votre VolleyError dans votre classe étendue Request. Un moyen très simple de gérer cela serait de faire quelque chose comme:

//In your extended request class
@Override
protected VolleyError parseNetworkError(VolleyError volleyError){
        if(volleyError.networkResponse != null && volleyError.networkResponse.data != null){
                VolleyError error = new VolleyError(new String(volleyError.networkResponse.data));
                volleyError = error;
            }

        return volleyError;
    }
}

Si vous ajoutez ceci à vos classes Request étendues, votre getMessage() ne devrait au moins pas renvoyer null. Normalement, cela ne me dérange pas vraiment, car il est assez facile de tout faire à partir de votre méthode onErrorResponse(VolleyError e).

Vous devriez utiliser une bibliothèque JSON pour simplifier les choses - j'utilise Gson par exemple, ou vous pouvez utiliser JSONObjects d'Apache, qui ne devrait pas nécessiter une bibliothèque externe supplémentaire. La première étape consiste à obtenir la réponse JSON envoyée par votre serveur sous forme de String (de la même manière que ce que je viens de démontrer). Ensuite, vous pouvez éventuellement la convertir en JSONObject ( en utilisant JSONObjects et JsonArrays d'Apache, ou une autre bibliothèque de votre choix) ou simplement analysez vous-même le String. Après cela, il vous suffit d’afficher le Toast.

Voici un exemple de code pour vous aider à démarrer:

public void onErrorResponse(VolleyError error) {
     String json = null;

     NetworkResponse response = error.networkResponse;
     if(response != null && response.data != null){
         switch(response.statusCode){
             case 400:
                  json = new String(response.data);
                  json = trimMessage(json, "message");
                  if(json != null) displayMessage(json);
                  break;
             }
            //Additional cases
     }
}

public String trimMessage(String json, String key){
    String trimmedString = null;

    try{
        JSONObject obj = new JSONObject(json);
        trimmedString = obj.getString(key);
    } catch(JSONException e){
        e.printStackTrace();
        return null;
    }

    return trimmedString;
}

//Somewhere that has access to a context
public void displayMessage(String toastString){
    Toast.makeText(context, toastString, Toast.LENGTH_LONG).show();
}
154
Submersed

essayez cette classe pour gérer toutes les erreurs

public class VolleyErrorHelper {
        /**
         * Returns appropriate message which is to be displayed to the user
         * against the specified error object.
         *
         * @param error
         * @param context
         * @return
         */

        public static String getMessage (Object error , Context context){
            if(error instanceof TimeoutError){
                return context.getResources().getString(R.string.timeout);
            }else if (isServerProblem(error)){
                return handleServerError(error ,context);

            }else if(isNetworkProblem(error)){
                return context.getResources().getString(R.string.nointernet);
            }
            return context.getResources().getString(R.string.generic_error);

        }

        private static String handleServerError(Object error, Context context) {

            VolleyError er = (VolleyError)error;
            NetworkResponse response = er.networkResponse;
            if(response != null){
                switch (response.statusCode){

                    case 404:
                    case 422:
                    case 401:
                        try {
                            // server might return error like this { "error": "Some error occured" }
                            // Use "Gson" to parse the result
                            HashMap<String, String> result = new Gson().fromJson(new String(response.data),
                                    new TypeToken<Map<String, String>>() {
                                    }.getType());

                            if (result != null && result.containsKey("error")) {
                                return result.get("error");
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        // invalid request
                        return ((VolleyError) error).getMessage();

                    default:
                        return context.getResources().getString(R.string.timeout);
                }
            }

            return context.getResources().getString(R.string.generic_error);
        }

        private static boolean isServerProblem(Object error) {
            return (error instanceof ServerError || error instanceof AuthFailureError);
        }

        private static boolean isNetworkProblem (Object error){
            return (error instanceof NetworkError || error instanceof NoConnectionError);
        }
6
Mina Fawzy