Déclaration du problème:
J'essaie d'accéder à une API REST qui renvoie un objet JSON pour divers codes d'état HTTP (400, 403, 200, etc.) à l'aide de Volley.
Pour tout statut HTTP autre que 200, il semble que le «code de réponse inattendu 400» pose problème. Quelqu'un at-il un moyen de contourner cette "erreur"?
Code:
protected void getLogin() {
final String mURL = "https://somesite.com/api/login";
EditText username = (EditText) findViewById(R.id.username);
EditText password = (EditText) findViewById(R.id.password);
// Post params to be sent to the server
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", username.getText().toString());
params.put("password", password.getText().toString());
JsonObjectRequest req = new JsonObjectRequest(mURL, new JSONObject(
params), new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONObject obj = response
.getJSONObject("some_json_obj");
Log.w("myApp",
"status code..." + obj.getString("name"));
// VolleyLog.v("Response:%n %s", response.toString(4));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.w("error in response", "Error: " + error.getMessage());
}
});
// add the request object to the queue to be executed
AppController.getInstance().addToRequestQueue(req);
}
Une façon de le faire sans changer le code source de Volley
consiste à rechercher les données de réponse dans VolleyError
et à les analyser vous-même.
À partir de f605da3 commit
, Volley
lève une exception ServerError
contenant la réponse réseau brute.
Vous pouvez donc faire quelque chose de similaire à ceci dans votre écouteur d’erreur:
/* import com.Android.volley.toolbox.HttpHeaderParser; */
public void onErrorResponse(VolleyError error) {
// As of f605da3 the following should work
NetworkResponse response = error.networkResponse;
if (error instanceof ServerError && response != null) {
try {
String res = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, "utf-8"));
// Now you can use any deserializer to make sense of data
JSONObject obj = new JSONObject(res);
} catch (UnsupportedEncodingException e1) {
// Couldn't properly decode data to string
e1.printStackTrace();
} catch (JSONException e2) {
// returned data is not JSONObject?
e2.printStackTrace();
}
}
}
Pour les futurs changements, si Volley
change, vous pouvez suivre l’approche ci-dessus dans laquelle vous devez rechercher dans VolleyError
les données brutes envoyées par le serveur et les analyser.
J'espère qu'ils implémenteront cette TODO
mentionnée dans le fichier source .
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
Vous devez ajouter Content-Type à l'en-tête.
Moi aussi j'ai eu la même erreur mais dans mon cas, j'appelais url avec des espaces.
Ensuite, je l'ai corrigé en analysant comme ci-dessous.
String url = "Your URL Link";
url = url.replaceAll(" ", "%20");
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new com.Android.volley.Response.Listener<String>() {
@Override
public void onResponse(String response) {
...
...
...
Essaye ça ...
StringRequest sr = new StringRequest(type,url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// valid response
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// error
}
}){
@Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<String, String>();
params.put("username", username);
params.put("password", password);
params.put("grant_type", "password");
return params;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
// Removed this line if you dont need it or Use application/json
// params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
Vous voulez dire que vous voulez obtenir des codes de statut?
VolleyError
a un type de variable membre NetworkResponse
et il est public.
Vous pouvez accéder à error.networkResponse.statusCode
pour le code d'erreur http.
J'espère que cela vous sera utile.
dans mon cas, je n'écrivais pas reg_url avec: 8080 . String reg_url = " http://192.168.29.163:8080/register.php ";
Ce que j'ai fait a été d'ajouter un '/' supplémentaire à mon URL, par exemple. :
String url = "http://www.google.com"
à
String url = "http://www.google.com/"
Juste pour tout mettre à jour, après quelques délibérations, j'ai décidé d'utiliser Async Http Client à la place pour résoudre mon problème précédent. La bibliothèque permet une approche plus propre ( pour moi ) pour manipuler les réponses HTTP, en particulier dans les cas où les objets JSON sont renvoyés dans tous les scénarios/statuts HTTP.
protected void getLogin() {
EditText username = (EditText) findViewById(R.id.username);
EditText password = (EditText) findViewById(R.id.password);
RequestParams params = new RequestParams();
params.put("username", username.getText().toString());
params.put("password", password.getText().toString());
RestClient.post(getHost() + "api/v1/auth/login", params,
new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers,
JSONObject response) {
try {
//process JSONObject obj
Log.w("myapp","success status code..." + statusCode);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers,
Throwable throwable, JSONObject errorResponse) {
Log.w("myapp", "failure status code..." + statusCode);
try {
//process JSONObject obj
Log.w("myapp", "error ..." + errorResponse.getString("message").toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}