2014-09-23 210 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

相關問題