I am using Volley successfully to pass and receive JSONArrays and JSONObjects, but the API I'm using requires that I pass in a simple Integer array [1,2,3] in a PUT request. Any ideas?
Here is a snippet from the API documentation.
PUT api/commuters/{id}/favorites
Update the list of favorite commuters associated with the specified
commuter.
REQUEST
Body Parameters: Collection of integer Request Formats
application/json, text/json, text/html Sample: [ 1, 2 ]
RESPONSE
none
The trick to sending text to a Volley Request is overriding the getBoddy method to print out your text/json.
Here is my method for putting the integer array:
public static void putFavorites(final JSONArray data, final MyApp.StringCallback callback) {
String url = APP_API + "commuters/" +
MyApp.getPrefs().getInt("commuterId", 0) + "/favorites";
StringRequest stringRequst = new StringRequest(Request.Method.PUT, url,
new Response.Listener<String>() {
#Override
public void onResponse(String result) {
try {
callback.onSuccess(result);
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
callback.onError(volleyError);
}
}) {
#Override
public String getBodyContentType() {
return "text/json";
}
#Override
public byte[] getBody() throws AuthFailureError {
Log.d(TAG, (data.toString()).getBytes().toString());
return (data.toString()).getBytes();
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> headers = VolleySingleton.getInstance(GACommuter.getAppContext()).getVolleyHeader("text/json");
return headers;
}
};
stringRequst.setRetryPolicy(new DefaultRetryPolicy(
20000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
));
addToRequestQueue(stringRequst);
}
Related
So i have a get request from an API, when i get the response i want to make that response into a json file instead of making him an JSONOBJECT, is it possible ? i will paste the get funcion here, and the way im getting the JSONOBJECT.
I want to replace the way i get a JSONOBJECT, from a way to get that json as a file that goes to my assets directory.
public void getAssetPlant(final VolleyCallBack callBack) {
RequestQueue requestQueue = Volley.newRequestQueue(this);
StringRequest request = new StringRequest(Request.Method.GET, url_assets, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject j = new JSONObject(response);
callBack.onSuccess();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MapActivity.this, "Failed to gather info" + error.networkResponse.statusCode, Toast.LENGTH_SHORT).show();
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
headers.put("Authorization", "Bearer " + token);
return headers;
}
};
requestQueue.add(request);
}
I'm finding the following error with my request post method: Unexpected response code 500 for POST method.
It was working fine and then it just stopped working and started to display this error.
this is my post method:
private void postRequest(String empresa, String matricula, String foto, String data, String face) {
RequestQueue requestQueue=Volley.newRequestQueue(MainActivity.this);
String url="http://can't show the url";
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//anĂ¡lise de dados json
try {
JSONObject jsonObject = new JSONObject(response);
}
catch (Exception e){
e.printStackTrace();
// post_response_text.setText("POST DATA : unable to Parse Json");
}
Log.d("Response", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// post_response_text.setText("Post Data : Response Failed");
Log.d("Error.Response", error.toString());
}
})
{
#Override
protected Map<String,String> getParams(){
Map<String,String> params=new HashMap<String, String>();
params.put("Id", "");
params.put("Empresa", empresa);
params.put("Matricula", matricula);
params.put("Foto", foto);
params.put("Data", data);
params.put("GPS", finalLatitude + "|" + finalLongitude);
params.put("idDispositivo", getIMEI());
params.put("arquivo", "");
params.put("face", face);
params.put("ip", getIP());
return params;
}
#Override
public Map<String,String> getHeaders() throws AuthFailureError {
Map<String,String> params=new HashMap<String, String>();
params.put("Content-Type","application/x-www-form-urlencoded");
return params;
}
};
stringRequest.setRetryPolicy(new DefaultRetryPolicy(
5000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(stringRequest);
}
I tried to do the post request on postman and it's working fine.
How i'm sending information on postman: postman image
So I am trying to parse an array of objects from json using Google's Gson library and Volley for HTTP requests. My issue is it's as if the code isn't 'hitting' the OnResponse call. I've tried adding a simple Log printout within the function just to see if it does anything.
My GsonRequest class comes straight from Google's Training Docs. I constructed these methods based on an answer to this question.
This is my code:
private void runVolleyJson() throws AuthFailureError {
GsonRequest<Meetings> getMeetings = new GsonRequest<Meetings>(AUTH_URL, Meetings.class, getHeaders(),
createMyReqSuccessListener(),
createMyReqErrorListener());
helper.add(getMeetings);
}
private Response.Listener<Meetings> createMyReqSuccessListener() {
return new Response.Listener<Meetings>() {
#Override
public void onResponse(Meetings response) {
// NOTHING HAPPENS FROM HERE!
try {
Log.d("response", response.toString());
} catch (Exception e) {
e.printStackTrace();
}
// Do whatever you want to do with response;
// Like response.tags.getListing_count(); etc. etc.
}
};
}
private Response.ErrorListener createMyReqErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Do whatever you want to do with error.getMessage();
}
};
}
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> map = new HashMap<>();
map.put("Content-Type", "application/json;");
map.put("Authorization", "Bearer <sometoken>");
return map;
}
There is absolutely no error. It is authorizing the request, but nothing happens in OnResponse, it just seems to ignore that function.
Now I've tried using a standard StringRequest with volley and it works flawlessly, like this:
private void runVolleyTest() {
StringRequest request = new StringRequest(Request.Method.GET, AUTH_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonarray = new JSONArray(response);
for(int i = 0; i < jsonarray.length(); i++) {
Gson gson = new Gson();
Meeting m = gson.fromJson(jsonarray.get(i).toString(), Meeting.class);
Log.e("Meeting", m.getMeetingId() + " " + m.getStatus());
}
} catch (JSONException e) {
e.printStackTrace();
}
;
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
txtError(error);
}
}) {
#Override
public Map<String, String> getHeaders() {
HashMap<String, String> map = new HashMap<>();
map.put("Content-Type", "application/json;");
map.put("Authorization", "Bearer <sometoken>");
return map;
}
};
//request.setPriority(Request.Priority.HIGH);
helper.add(request);
}
Try adding this line at the beginning
RequestQueue helper = Volley.newRequestQueue(mContext);
Add these line
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.add(stringRequest);
if you don't want to the save response in cache memory then add this
requestQueue.add(stringRequest);
According to my personal opinion its better if you pass the application context.
I am new to using Volley on Android. Using the old http client stuff I could make my web requests perfectly with the various headers and parameters, now I am unable. My request looks like this in Postman:
POST /token HTTP/1.1
Host: my.api.co.za
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
username=test&password=1234&grant_type=password
Yet I am unable to recreate and execute this request in Volley. I have tried making a custom Json request class that extends Request<JSONObject> but to no avail. Please see my code below:
public class CustomJsonRequest extends Request<JSONObject> {
private Response.Listener<JSONObject> listener;
private Map<String, String> params;
public CustomJsonRequest(int method, String url, Listener<JSONObject> responseListener, ErrorListener errorListener) {
super(method, url, errorListener);
this.listener = responseListener;
}
#Override
public Map getHeaders() throws AuthFailureError {
Map headers = new HashMap();
headers.put("Accept", "application/json");
headers.put("Content-Type", "application/x-www-form-urlencoded");
return headers;
}
#Override
public byte[] getBody() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", "test");
params.put("password", "1234");
params.put("grant_type", "password");
if (params != null && params.size() > 0) {
return encodeParameters(params, getParamsEncoding());
}
return null;
}
/**
* Converts <code>params</code> into an application/x-www-form-urlencoded encoded string.
*/
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('&');
}
encodedParams.deleteCharAt(encodedParams.lastIndexOf("&"));
Log.e("params", encodedParams.toString());
return encodedParams.toString().getBytes(paramsEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
Log.e("response", response.toString());
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
#Override
protected void deliverResponse(JSONObject response) {
// TODO Auto-generated method stub
Log.e("response", response.toString());
listener.onResponse(response);
}
private Priority mPriority;
public void setPriority(Priority priority) {
mPriority = priority;
}
#Override
public Priority getPriority() {
return mPriority == null ? Priority.NORMAL : mPriority;
}
}
And I call this as follows in my MainActivity class:
CustomJsonRequest request = new CustomJsonRequest(Request.Method.POST, AUTH_URL, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//showJSON(response);
VolleyLog.v("Response:%n %s", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
txtError(error);
}
});
Can somebody tell me where I am going wrong in creating this request?
You can try with my following sample code:
String url = "http://server/token";
Map<String, String> stringMap = new HashMap<>();
stringMap.put("grant_type", "password");
stringMap.put("username", "bnk");
stringMap.put("password", "bnk123");
Uri.Builder builder = new Uri.Builder();
Iterator entries = stringMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
builder.appendQueryParameter(entry.getKey().toString(), entry.getValue().toString());
entries.remove();
}
String requestBody = builder.build().getEncodedQuery();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, requestBody, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// do something...
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// do something...
}
}){
#Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded";
}
};
UPDATE:
If your project uses Google's official volley as a module, you should add the following into JsonObjectRequest.java file:
public JsonObjectRequest(int method, String url, String requestBody,
Listener<JSONObject> listener, ErrorListener errorListener) {
super(method, url, requestBody, listener, errorListener);
}
UPDATE 2:
If you don't want to edit JsonObjectRequest.java file as I mentioned above, you can use the following code:
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// do something...
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// do something...
}
}) {
#Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded";
}
#Override
public byte[] getBody() {
// init parameters
Map<String, String> params = new HashMap<>();
params.put("grant_type", "password");
params.put("username", "bnk");
params.put("password", "bnk123");
// encode parameters (can use Uri.Builder as above)
String paramsEncoding = "UTF-8";
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);
}
}
};
Hope it helps!
I am using Volley to fetch data from a REST service. So there are two methods , One is POST which creates an object on server and other is PUT which basically updates the same object.I use the same code for making these requests.I just change the Method which is passed in Volley.The app works fine through POST request with the correct data sent in the body, but it encounters a problem with PUT request where it randomly sends no data in the body.
I shifted to a custom Request object as suggested by Google but it is still not working.
int method = Request.Method.POST;
String objID = sharedPreferences.getString("objID", null);
String Url = "/api_url";
if (objID != null)
{
Url += objID + "/";
method = Request.Method.PUT;
}
try
{
JSONObject objJSON = new JSONObject();
objJSON.put("name", "new_name");
}
catch (JSONException e)
{
// Handle Execption
}
GsonRequest request = new GsonRequest<CustomObj>(method, Url, CustomObj.class,null, null, objJSON.toString(),
new Response.Listener<CustomObj>()
{
#Override
public void onResponse(CartObj cartObj)
{
// Handling Logic
}
}
,
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError volleyError)
{
// Handle Error
}
});
VolleySingleton.getInstance(this).addToRequestQueue(request);
GsonRequest is my Custom Class Extending Request Object
public class GsonRequest<T> extends Request<T>
{
private final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
private final Listener<T> listener;
private final Map<String, String> params;
private final String body;
private ErrorListener mErrorListener;
/**
* Make a GET request and return a parsed object from JSON.
*
* #param url URL of the request to make
* #param clazz Relevant class object, for Gson's reflection
* #param headers Map of request headers
*/
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Map<String, String> params, String body, Listener<T> listener, ErrorListener errorListener)
{
super(method, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
this.params = params;
this.body = body;
this.mErrorListener = errorListener;
}
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Map<String, String> params, Listener<T> listener, ErrorListener errorListener)
{
this(method, url, clazz, headers, params, null, listener, errorListener);
}
public GsonRequest(int method, String url, Class<T> clazz, Map<String, String> headers, Listener<T> listener, ErrorListener errorListener)
{
this(method, url, clazz, headers, null, null, listener, errorListener);
}
#Override
public byte[] getBody() throws AuthFailureError
{
return body != null ? body.getBytes() : super.getBody();
}
#Override
protected Map<String, String> getParams() throws AuthFailureError
{
return params != null ? params : super.getParams();
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError
{
return headers != null ? headers : super.getHeaders();
}
#Override
protected void deliverResponse(T response)
{
listener.onResponse(response);
}
#Override
public void deliverError(VolleyError error)
{
mErrorListener.onErrorResponse(error);
}
#SuppressWarnings("unchecked")
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response)
{
try
{
String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(gson.fromJson(json, clazz), HttpHeaderParser.parseCacheHeaders(response));
}
catch (UnsupportedEncodingException e)
{
return Response.error(new ParseError(e));
}
catch (JsonSyntaxException e)
{
return Response.error(new ParseError(e));
}
}
}
I am using GSON to parse my Data , and CustomObj is a Mapping Object for volley.
First of all all make sure the url you're building (where you check if objID is not null) is correct.
Secondly, you can try to call getBytes() method with a charset.
In the request override getBody() method:
#Override
public byte[] getBody() throws AuthFailureError {
try {
return body != null ? body.getBytes(getParamsEncoding()) : super.getBody();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return super.getBody();
}
Hope this will help.
Edit:
You can also try to override getBodyContentType() method:
#Override
public String getBodyContentType() {
return "application/json; charset=" + getParamsEncoding();
}