Je veux faire un POST JSONObjectRequest avec les paramètres du formulaire urlencoded. Comment puis-je faire cela? J'ai essayé le code suivant, mais en vain.
final String api = "http://api.url";
final JSONObject jobj = new JSONObject();
jobj.put("Username", "usr");
jobj.put("Password", "passwd");
jobj.put("grant_type", "password");
final JsonObjectRequest jor = new JsonObjectRequest(
Request.Method.POST,
api, jobj,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Toast.makeText(getApplicationContext(), "Login Successful!", Toast.LENGTH_LONG).show();
//do other things with the received JSONObject
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "Error!", Toast.LENGTH_LONG).show();
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> pars = new HashMap<String, String>();
pars.put("Content-Type", "application/x-www-form-urlencoded");
return pars;
}
};
//add to the request queue
requestqueue.AddToRequestQueue(jor);
Je reçois une 400 mauvaise requête avec l'appel API! Comment puis-je le réparer?
Après une longue et longue lutte, a trouvé la solution. Vous devez remplacer getBodyContentType()
et retourner application/x-www-form-urlencoded; charset=UTF-8
.
StringRequest jsonObjRequest = new StringRequest(
Request.Method.POST,
getResources().getString(R.string.base_url),
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
MyFunctions.toastShort(LoginActivity.this, response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("volley", "Error: " + error.getMessage());
error.printStackTrace();
MyFunctions.croutonAlert(LoginActivity.this,
MyFunctions.parseVolleyError(error));
loading.setVisibility(View.GONE);
}
}) {
@Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=UTF-8";
}
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("username", etUname.getText().toString().trim());
params.put("password", etPass.getText().toString().trim());
return params;
}
};
AppController.getInstance().addToRequestQueue(jsonObjRequest);
public static void DoPostStringResult(String url, Object Tag,
final StringCallBack CallBack, Context context,
final String body) {
StringRequest request = new StringRequest(Request.Method.POST, url,
new Listener<String>() {
@Override
public void onResponse(String result) {
CallBack.getResult(result);
}
}, new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
CallBack.getError(error);
}
}) {
// @Override
// public Map<String, String> getHeaders() throws AuthFailureError {
// //设置头信息
// Map<String, String> map = new HashMap<String, String>();
// map.put("Content-Type", "application/x-www-form-urldecoded");
// return map;
// }
@Override
public byte[] getBody() throws AuthFailureError {
// TODO Auto-generated method stub
return body.getBytes();
}
@Override
public String getBodyContentType() {
// TODO Auto-generated method stub
return "application/x-www-form-urlencoded";
}
/**
* 设置Volley网络请求的编码方式。。。。
*/
@Override
protected String getParamsEncoding() {
return "utf-8";
}
};
request.setRetryPolicy(new DefaultRetryPolicy(30 * 1000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
request.setTag(Tag);
VolleyUtils.getRequestQueue(context).add(request);
}
et votre corps doit être comme ceci "username=aa&password=bb&[email protected]"
essayez d'utiliser StringRequest
comme le code ci-dessous:
final String api = "http://api.url";
final StringRequest stringReq = new StringRequest(Request.Method.POST, api, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Toast.makeText(getApplicationContext(), "Login Successful!", Toast.LENGTH_LONG).show();
//do other things with the received JSONObject
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "Error!", Toast.LENGTH_LONG).show();
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> pars = new HashMap<String, String>();
pars.put("Content-Type", "application/x-www-form-urlencoded");
return pars;
}
@Override
public Map<String, String> getParams() throws AuthFailureError {
Map<String, String> pars = new HashMap<String, String>();
pars.put("Username", "usr");
pars.put("Password", "passwd");
pars.put("grant_type", "password");
return pars;
}
};
//add to the request queue
requestqueue.AddToRequestQueue(stringReq);
Volley ajoute un en-tête Content-Type juste avant l'envoi de la demande.
/**
* Returns the content type of the POST or PUT body.
*/
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=" + getParamsEncoding();
}
Vous devez remplacer cela par un objet de demande personnalisé.
public class CustomVolleyRequest extends StringRequest {
...
@Override
public String getBodyContentType() {
return "application/json";
}
...
}
Je l'ai fait de la manière suivante (le type de contenu de mon corps de demande était application/x-www-form-urlencoded):
J'ai commenté aux endroits appropriés dans le code.
/**
* @param url - endpoint url of the call
* @param requestBody - I'm receiving it in json, without any encoding from respective activities.
* @param listener - StringRequestListener is an Interface I created to handle the results in respective activities
* @param activity - just for the context, skippable.
* @param header - This contains my x-api-key
*/
public void makePostRequest2(String url, final JSONObject requestBody, final StringRequestListener listener,
Activity activity, final Map<String,String> header) {
RequestQueue queue = VolleySingleton.getInstance().getRequestQueue();
/**
* You can skip this network testing.
*/
if(!NetworkTester.isNetworkAvailable()) {
Toast.makeText(MyApplication.getAppContext(),"Network error",Toast.LENGTH_SHORT).show();
return;
}
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
listener.onResponse(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
listener.onError(error);
}
}) {
/**
* Setting the body-content type is the most important part.
* @return
* You don't have to write this method if your body content-type is application/x-www-form-urlencoded and encoding is charset=UTF-8
* Because the base method is does the exact same thing.
*/
// @Override
// public String getBodyContentType() {
// return "application/x-www-form-urlencoded; charset=UTF-8";
// }
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return header;
}
/**
* I have copied the style of this method from its original method from com.Android.Volley.Request
* @return
* @throws AuthFailureError
*/
@Override
public byte[] getBody() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
try {
params.put("grant_type","password");
params.put("username",requestBody.getString("username"));
params.put("password",requestBody.getString("password"));
} catch (JSONException e) {
e.printStackTrace();
}
//yeah, I copied this from the base method.
if (params != null && params.size() > 0) {
return encodeParameters(params, getParamsEncoding());
}
return null;
}
};
queue.add(stringRequest);
}
/**
* This method was private in the com.Android.Volley.Request class. I had to copy it here so as to encode my paramters.
* @param params
* @param paramsEncoding
* @return
*/
private byte[] encodeParameters(Map<String, String> params, String paramsEncoding) {
StringBuilder encodedParams = new StringBuilder();
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding));
encodedParams.append('=');
encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding));
encodedParams.append('&');
}
return encodedParams.toString().getBytes(paramsEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
public void sendUserRegistrationRequest(final UserRequest userRequest, final ResponseListener responseListener) {
String url = Api.POST_NRNA_REGISTRATION;
StringRequest userRegistrationRequest = new StringRequest(Request.Method.POST, url, new com.Android.volley.Response.Listener<String>() {
@Override
public void onResponse(String response) {
JSONObject jsonObject = GsonUtils.getJSONObject(response);
LoggerUtils.log(TAG, "" + jsonObject.toString());
}
}, new com.Android.volley.Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
LoggerUtils.log(TAG, GsonUtils.toString(error));
responseListener.onError(GsonUtils.toString(error));
}
}) {
//use this if you have to use form posting : for application/x-www-form-urlencoded;
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return GsonUtils.getHashMap(userRequest);
}
@Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=UTF-8";
}
};
VolleyRequestQueue.getInstance(context).addToRequestQueue(userRegistrationRequest);
}
Utilisez-le si vous devez envoyer comme "application/json"
@Override
public byte[] getBody() throws AuthFailureError {
String jsonData = GsonUtils.toString(userRequest);
return jsonData.getBytes();
}
@Override
public String getBodyContentType() {
return "application/json";
}
public class GsonUtils {
public static String TAG = GsonUtils.class.getSimpleName();
public static <T> T toObject(String data, Class<T> type) {
Gson gson = new Gson();
return gson.fromJson(data, type);
}
public static String toString(Object src) {
if (src == null) {
return null;
}
GsonBuilder builder = new GsonBuilder();
builder.setPrettyPrinting();
Gson gson = builder.create();
return gson.toJson(src);
}
public static <T> T toObject(String data, Type type) {
try {
Gson gson = new Gson();
return gson.fromJson(data, type);
} catch (Exception ex) {
Timber.v(ex.getMessage());
return null;
}
}
public static JSONObject getJSONObject(Object src) {
String data = toString(src);
LoggerUtils.log(TAG, data);
try {
return new JSONObject(data);
} catch (JSONException e) {
LoggerUtils.log(TAG, e.getMessage());
}
return null;
}
public static JSONObject getJSONObject(String data) {
try {
return new JSONObject(data);
} catch (JSONException e) {
LoggerUtils.log(TAG, e.getMessage());
}
return null;
}
public static HashMap<String, String> getHashMap(Object src) {
String data = toString(src);
LoggerUtils.log(TAG, data);
return toObject(data, new TypeToken<HashMap<String, String>>() {
}.getType());
}
}
Il n'y a pas de constructeur prédéfini dans JsonObjectRequest
qui accepte les paramètres de publication, vous avez donc créé votre propre constructeur
Vous devez à la fois affecter votre Map à une variable déjà déclarée dans cette méthode dans votre constructeur, et vous devez également ajouter cette méthode
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return this.params;
}