2014-09-23 132 views
25

我想使用表单urlencoded参数创建POST JSONObjectRequest。我怎样才能做到这一点?我试过下面的代码,但无济于事。在发布请求中发送表单urlencoded参数android volley

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

我得到一个400坏请求与API调用!我该如何解决它?

回答

2

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

对不起,没有运气!仍然是400错误! – user4071017 2014-09-23 16:29:38

+0

这意味着您所做的请求不正确。检查API文档和您发送的内容,并确保它是正确的。你可以发送你的请求与一些其他的东西,如邮递员或RESTClient,并告诉我结果? – mmlooloo 2014-09-23 16:40:13

+0

一切工作与邮递员:( – user4071017 2014-09-23 16:45:38

0

有一个在JsonObjectRequest没有预先做好的构造函数,它接受后的参数,让你做你自己的构造

你必须同时分配您的地图已声明变量在您的构造函数中的该方法中,并且您还必须添加此方法

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

_you必须同时指定你的在构造函数中映射到该方法中已经声明的变量_请解释! – user4071017 2014-09-23 16:38:23

+0

@ user4071017好吧,您必须在您的Volley项目中修改文件“JsonObjectRequest.java”。添加代码'Map param;'然后在您的构造函数中添加'this.params = jobj;' – CQM 2014-09-23 16:49:37

+0

@ user4071017对不起,您需要学习Java基础以继续。 – CQM 2014-09-23 18:19:45

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

,你的身体必须是这样的“用户名= AA &密码= BB & [email protected]

+0

嗨,你能告诉我它的工作方式吗?因为我在这里面对上面的代码请求错误。 – 2017-05-26 07:05:58

51

亚特很长很长的斗争,找到了解决办法。您需要重写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); 
+1

ü使我的一天:) – stefan 2015-08-05 12:18:32

+0

完美的方式<3 – amirsa00 2017-01-10 11:14:30

+0

感谢您的答案工作对我来说 – 2017-05-26 10:37:35

2

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

      ... 
    } 
1

我做到了以下方式(内容类型我的请求体的是应用程序/ x-WWW的形式,进行了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); 
     } 
    } 
0
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); 
} 

使用这个,如果你要送样 “应用/ 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()); 
} 

}

+0

你从哪里得到GsonUtils? – 2017-10-26 06:24:21

+0

我建议使用改造,它是一个伟大的图书馆的android网络 – 2017-10-27 11:28:16