フォームurlencodedパラメーターを使用してPOST JSONObjectRequestを作成します。これを行うにはどうすればよいですか?次のコードを試しましたが、役に立ちませんでした。
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);
API呼び出しで400件の悪いリクエストを受け取っています!どうすれば修正できますか?
長い長い闘争の後、解決策を見つけました。 getBodyContentType()
をオーバーライドして、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);
}
そして、あなたの体は次のようなものでなければなりません。「username=aa&password=bb&[email protected]」
以下のコードのようにStringRequest
を使用してみてください:
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は、リクエストが送信される直前にContent-Typeヘッダーを追加します。
/**
* Returns the content type of the POST or PUT body.
*/
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=" + getParamsEncoding();
}
カスタムリクエストオブジェクトでこれをオーバーライドする必要があります。
public class CustomVolleyRequest extends StringRequest {
...
@Override
public String getBodyContentType() {
return "application/json";
}
...
}
私はそれを次のように行いました(私のリクエストボディのコンテンツタイプはapplication/x-www-form-urlencodedでした):
コード内の適切な場所でコメントしました。
/**
* @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);
}
「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());
}
}
JsonObjectRequest
にはpostパラメーターを受け入れる事前作成されたコンストラクターがないため、独自のコンストラクターを作成しました
コンストラクタ内でそのメソッドで既に宣言されている変数にマップを割り当てる必要があり、このメソッドを追加する必要があります
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return this.params;
}