在post请求android volley中发送表单urlencoded参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25998529/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:55:22  来源:igfitidea点击:

Send form-urlencoded parameters in post request android volley

androidandroid-volley

提问by user4071017

I want to make a POST JSONObjectRequest with form urlencoded parameters. How can I do this? I've tried the following code, but to no avail.

我想用表单 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);

I'm getting a 400 bad request with the api call! How can I fix it?

我通过 api 调用收到 400 个错误的请求!我该如何解决?

回答by Bala Vishnu

Ater a long long struggle, found the solution. You need to override getBodyContentType()and return application/x-www-form-urlencoded; charset=UTF-8.

经过长时间的斗争,找到了解决方案。您需要覆盖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);

回答by TheOne_su

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

and your body must be like this "username=aa&password=bb&[email protected]"

而你的正文必须是这样的“username=aa&password=bb&[email protected]

回答by mmlooloo

try using StringRequestlike below code:

尝试使用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);

回答by shakrlabs.com

Volley adds a Content-Type header right before the request is sent out.

Volley 在发出请求之前添加了一个 Content-Type 标头。

     /**
     * Returns the content type of the POST or PUT body.
     */
     public String getBodyContentType() {
         return "application/x-www-form-urlencoded; charset=" + getParamsEncoding();
      }

You must override this with a custom request object.

您必须使用自定义请求对象覆盖它。

    public class CustomVolleyRequest extends StringRequest {
           ...

           @Override
           public String getBodyContentType() {
                return "application/json";
           }               

           ...
    }

回答by Akeshwar Jha

I did it the following way (the content-type of my request-body was application/x-www-form-urlencoded):

我是按照以下方式完成的(我的请求正文的内容类型是 application/x-www-form-urlencoded):

I've commented at appropriate places in the 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);
        }
    }

回答by Prabin Shrestha

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

Use this if you have to send like "application/json"

如果您必须像“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());
}

}

}

回答by CQM

There is no premade constructor in JsonObjectRequestthat accepts post parameters, so you made your own constructor

没有JsonObjectRequest接受 post 参数的预制构造函数,所以你制作了自己的构造函数

You have to both assign your Map to an already declared variable in that method within your constructor, and you also have to add this method

您必须将 Map 分配给构造函数中该方法中已声明的变量,并且还必须添加此方法

@Override
protected Map<String, String> getParams() throws AuthFailureError {
    return this.params;
}