I'm trying to send a POST request with paramteres to server. But the post params are always null.
I've tried few solutions from stackoverflow but it didn't work.
I get Unexpected response code 401 for 11.urlname
Map<String, String> jsonParams = new HashMap<String, String>();
jsonParams.put("username", "test#mail.com");
jsonParams.put("usertype", "userType");
jsonParams.put("apikey", "key");
JsonObjectRequest myRequest = new JsonObjectRequest(Request.Method.POST,apiURL, new JSONObject(jsonParams),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String status=response.getString("status");
if (status.equals("success"))
{
txtResponse.setText("Valid user");
}
else {
txtResponse.setText("InValid USer");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=UTF-8");
return headers;
}
};
AppController.getInstance().addToRequestQueue(myRequest, "tag");
My App controller code is
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
If your issue has not been solved, you can refer to the following code to build your request body (params)
private String buildRequestBody(Object content) {
String output = null;
if ((content instanceof String) ||
(content instanceof JSONObject) ||
(content instanceof JSONArray)) {
output = content.toString();
} else if (content instanceof Map) {
Uri.Builder builder = new Uri.Builder();
HashMap hashMap = (HashMap) content;
if (isValid(hashMap)) {
Iterator entries = hashMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
builder.appendQueryParameter(entry.getKey().toString(), entry.getValue().toString());
entries.remove(); // avoids a ConcurrentModificationException
}
output = builder.build().getEncodedQuery();
}
}
return output;
}
Then...
Map<String, String> stringMap = new HashMap<>();
stringMap.put("username", "yourusername");
stringMap.put("password", "yourpassword");
...
String requestBody = buildRequestBody(stringMap);
Related
I sent request with postman its working, but volley doesn't work. I always get error! I searched stackoverflow volley returns error when response is empty but i added CustomJsonObjectRequest still the issue remains.
Error message
Volley org.json.JSONException: End of input at character 0 of
CustomJsonObjectRequest
public class CustomJsonObjectRequest extends JsonObjectRequest {
public CustomJsonObjectRequest(int method, String url, JSONObject jsonRequest, Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
super(method, url, jsonRequest, listener, errorListener);
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
if (response.data.length == 0) {
byte[] responseData = "{}".getBytes("UTF8");
response = new NetworkResponse(response.statusCode, responseData, response.headers, response.notModified);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return super.parseNetworkResponse(response);
}
}
Volley request
EcoElement ecoElement = ecoElementArrayList.get(position);
Map<String, String> params = new HashMap<String, String>();
params.put("Id", ecoElement.getId().toString());
params.put("Checked", ecoElement.getChecked().toString());
JSONObject ObjParams = new JSONObject(params);
try {
CustomJsonObjectRequest getRequest = new CustomJsonObjectRequest(Request.Method.PUT, "https://ourwebsite.sslbeta.de/api/gardenapi/updateecoelements", ObjParams,
response -> {
Toast.makeText(getContext(), ""+response, Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
},
error -> {
Toast.makeText(getContext(), ""+error.toString(), Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
);
RequestQueueSingleton.getInstance(getContext()).addToRequestQueue(getRequest);
} catch (Exception e) {
Toast.makeText(getContext(), e.toString(), Toast.LENGTH_LONG).show();
}
Finally i was able to fix the issues after hours of searching. There were two reasons to this, first is that api was returning null/empty so CustomJsonObjectRequest fixed that, and then another issue is that i forgot to add authentication headers. that was a silly mistake i know!
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json");
headers.put("Authorization", "Bearer "+access_token);
return headers;
}
};
Here is the solution, just create this method and pass your value.
private void CustomJsonObjectRequest() {
String tag_string_req = "req__details";
StringRequest strReq = new StringRequest(Request.Method.POST, <API URL>, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
getPerspective().showErrorLogs(TAG, "Response Invest : " + response);
try {
// Parse your response here
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("Id", <ID VALUE HERE>);
params.put("Checked", <TRUE or FALSE>);
return params;
}
};
strReq.setRetryPolicy(new RetryPolicy() {
#Override
public void retry(VolleyError arg0) throws VolleyError {
}
#Override
public int getCurrentTimeout() {
return 0;
}
#Override
public int getCurrentRetryCount() {
return 0;
}
});
strReq.setShouldCache(false);
addToRequestQueue(strReq, tag_string_req);
}
Both ID and Checked must have String type.And create below methods in MainActivity:
private RequestQueue mRequestQueue;
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
Is it possible to change the value of global variable or to return value from volley method. Im trying to return value but im not getting any value from this method. I need to return 'listaFilmovaSerija' ArrayList.
public static ArrayList<MoviesShowsModel> readJSON(Context context, String url, final ArrayList<MoviesShowsModel> listaFilmovaSerija, final boolean odredjenaVelicina){
requestQueue = Volley.newRequestQueue(context);
listaFilmovaSerija.clear();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,
url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String naslov = "";
JSONObject obj = new JSONObject(response.toString());
JSONArray arr = obj.getJSONArray("results");
int d = (odredjenaVelicina)? 10 : arr.length();
for (int i = 0; i < d; i++){
JSONObject obj2 = arr.getJSONObject(i);
naslov = (getTabActive() == 0)? obj2.getString("title") : obj2.getString("name");
listaFilmovaSerija.add(new MoviesShowsModel(naslov,
obj2.getString("poster_path"),
obj2.getString("overview"),
obj2.getString("backdrop_path"),
obj2.getInt("id")));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("ISPIS","Desila se greska " + error);
}
});
requestQueue.add(jsonObjectRequest);
return listaFilmovaSerija;}
To get the response in ArrayList you have to implement Custom request of type ArrayList then only you will be able to get the desired response.
You can read about it in official documentation
and you can find tutorial here
Example from Official documentation which is Custom GsonRequest
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;
/**
* 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(String url, Class<T> clazz, Map<String, String> headers,
Listener<T> listener, ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.clazz = clazz;
this.headers = headers;
this.listener = listener;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
#Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
#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 wan't send post from JsonArrayRequest to server and I found some answer and I trying it..
but I got error like this
this is my code
HashMap<String, String> params = new HashMap<String, String>();
public void JSON_DATA_WEB_CALL() {
jsonArrayRequest = new JsonArrayRequest(GET_JSON_DATA_HTTP_URL, new JSONObject(params),
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
JSON_PARSE_DATA_AFTER_WEBCALL(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("CUSTOM_HEADER", "Yahoo");
headers.put("ANOTHER_CUSTOM_HEADER", "Google");
return headers;
}
};
requestQueue = Volley.newRequestQueue(this);
requestQueue.add(jsonArrayRequest);
}
how to fix that?
Use this custom class.
public class CustomJsonArrayRequest extends JsonRequest<JSONArray> {
/**
* Creates a new request.
* #param method the HTTP method to use
* #param url URL to fetch the JSON from
* #param jsonRequest A {#link JSONObject} to post with the request. Null is allowed and
* indicates no parameters will be posted along with request.
* #param listener Listener to receive the JSON response
* #param errorListener Error listener, or null to ignore errors.
*/
public CustomJsonArrayRequest(int method, String url, JSONObject jsonRequest,
Response.Listener<JSONArray> listener, Response.ErrorListener errorListener) {
super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener,
errorListener);
}
#Override
protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, PROTOCOL_CHARSET));
return Response.success(new JSONArray(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}
}
Implementation in your case should be something like this:
HashMap<String, String> params = new HashMap<String, String>();
public void JSON_DATA_WEB_CALL() {
CustomJsonArrayRequest request = new CustomJsonArrayRequest (Request.Method.POST, GET_JSON_DATA_HTTP_URL, new JSONObject(params),
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
JSON_PARSE_DATA_AFTER_WEBCALL(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("CUSTOM_HEADER", "Yahoo");
headers.put("ANOTHER_CUSTOM_HEADER", "Google");
return headers;
}
};
requestQueue = Volley.newRequestQueue(this);
requestQueue.add(request);
}
Please, I don't know where add/edit timeout and Retry Policy.
Basically I would have a 3 sec. of timeout, and rety policy set to zero.
I'm using a pattern found on web.
Controller.java
public class Controller extends Application {
/**
* Log or request TAG
*/
public static final String TAG = "VolleyPatterns";
/**
* Global request queue for Volley
*/
private RequestQueue mRequestQueue;
#Override
public void onCreate() {
super.onCreate();
}
/**
* #return The Volley Request queue, the queue will be created if it is null
*/
public RequestQueue getRequestQueue() {
// lazy initialize the request queue, the queue instance will be
// created when it is accessed for the first time
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
/**
* Adds the specified request to the global queue, if tag is specified
* then it is used else Default TAG is used.
*
* #param req
* #param tag
*/
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
VolleyLog.d("Adding request to queue: %s", req.getUrl());
getRequestQueue().add(req);
}
/**
* Adds the specified request to the global queue using the Default TAG.
*
* #param req
* #param tag
*/
public <T> void addToRequestQueue(Request<T> req) {
// set the default tag if tag is empty
req.setTag(TAG);
getRequestQueue().add(req);
}
/**
* Cancels all pending requests by the specified TAG, it is important
* to specify a TAG so that the pending/ongoing requests can be cancelled.
*
* #param tag
*/
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
BaseController.java
public class BaseController extends Controller {
/**
* A singleton instance of the application class for easy access in other places
*/
private static Controller sInstance;
private static String mToken = null;
#Override
public void onCreate() {
super.onCreate();
// initialize the singleton
sInstance = this;
}
public static void setMtoken(String token){
mToken = token;
}
public static String getMtoken(){
return mToken;
}
/**
* #return ApplicationController singleton instance
*/
public static synchronized Controller getInstance() {
return sInstance;
}
}
CustomRequest.java
public class CustomRequest extends Request<JSONObject> {
private Response.Listener<JSONObject> listener;
private Map<String, String> params;
public CustomRequest(String url, Map<String, String> params,
Response.Listener<JSONObject> reponseListener, Response.ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.listener = reponseListener;
this.params = params;
}
public CustomRequest(int method, String url, Map<String, String> params,
Response.Listener<JSONObject> reponseListener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.listener = reponseListener;
this.params = params;
}
#Override
protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
return params;
};
#Override
protected void deliverResponse(JSONObject response) {
listener.onResponse(response);
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
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));
}
}
}
And final this is a real API call:
public void login(final VolleyCallback<String> callback, String username, String password) {
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", username);
params.put("password", password);
CustomRequest jsObjRequest = new CustomRequest(Request.Method.POST,
API_URL_LOGIN, params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray account = response.optJSONArray("account");
if (account!=null) {
account = response.getJSONArray("account");
JSONObject account2 = account.getJSONObject(0);
String token = account2.getString("token");
if (token!="null" && token!=null && token!="" && !token.isEmpty()) {
callback.onSuccess(token);
} else {
// token doens't set
String result = "NO_TOKEN";
callback.onSuccess(result);
}
} else {
// WRONG PASSWORD
String result = "WRONG_PASSWORD";
callback.onSuccess(result);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError response) {
if(response instanceof NoConnectionError) {
/*
showDialog(LoginActivity.this,
LoginActivity.this.getString(R.string.title_no_internet_connection),
LoginActivity.this.getString(R.string.message_no_internet_connection));*/
}
}
});
// add the request object to the queue to be executed
BaseController.getInstance().addToRequestQueue(jsObjRequest);
}
You can set Retry Policy to the request before adding it to queue
jsObjRequest.setRetryPolicy(new DefaultRetryPolicy(
3000,
0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
//Adding the request to queue
BaseController.getInstance().addToRequestQueue(jsObjRequest);
This stack overflow question would help you.
I need to parse a custom object that contains another custom object. I have two custom objects: Page and Widget, the Page object has a HashTable of Widget. I want to parse JSON and create an array of Page with various Widget. My request class is:
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 Response.Listener<T> listener;
private final Map<String, String> params;
public GsonRequest(String url, Class<T> classType, HashMap<String, String> params, Response.Listener<T> listener, Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
headers = null;
this.clazz = classType;
this.listener = listener;
this.params = params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
#Override
protected void deliverResponse(T response) {
listener.onResponse(response);
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
return params;
}
#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));
}
}
GsonRequest<Page[]> req = new GsonRequest<Page[]>(url, V10Page[].class, params, new Response.Listener<Page[]>() {
#Override
public void onResponse(Page[] response) {
List<Page> lista = Arrays.asList(response);
//callback.onSuccess(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("Error:" + error.getLocalizedMessage());
}
});
}
The problem is that all the obejcts are null, where is the mistake?