I saw Google IO 2013 session about Volley and I'm considering switching to volley. Does Volley support adding POST/GET parameters to request? If yes, how can I do it?
For the GET parameters there are two alternatives:
First: As suggested in a comment bellow the question you can just use String and replace the parameters placeholders with their values like:
String uri = String.format("http://somesite.com/some_endpoint.php?param1=%1$s¶m2=%2$s",
num1,
num2);
StringRequest myReq = new StringRequest(Method.GET,
uri,
createMyReqSuccessListener(),
createMyReqErrorListener());
queue.add(myReq);
where num1 and num2 are String variables that contain your values.
Second: If you are using newer external HttpClient (4.2.x for example) you can use URIBuilder to build your Uri. Advantage is that if your uri string already has parameters in it it will be easier to pass it to the URIBuilder and then use ub.setQuery(URLEncodedUtils.format(getGetParams(), "UTF-8")); to add your additional parameters. That way you will not bother to check if "?" is already added to the uri or to miss some & thus eliminating a source for potential errors.
For the POST parameters probably sometimes will be easier than the accepted answer to do it like:
StringRequest myReq = new StringRequest(Method.POST,
"http://somesite.com/some_endpoint.php",
createMyReqSuccessListener(),
createMyReqErrorListener()) {
protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("param1", num1);
params.put("param2", num2);
return params;
};
};
queue.add(myReq);
e.g. to just override the getParams() method.
You can find a working example (along with many other basic Volley examples) in the Andorid Volley Examples project.
In your Request class (that extends Request), override the getParams() method. You would do the same for headers, just override getHeaders().
If you look at PostWithBody class in TestRequest.java in Volley tests, you'll find an example.
It goes something like this
public class LoginRequest extends Request<String> {
// ... other methods go here
private Map<String, String> mParams;
public LoginRequest(String param1, String param2, Listener<String> listener, ErrorListener errorListener) {
super(Method.POST, "http://test.url", errorListener);
mListener = listener;
mParams = new HashMap<String, String>();
mParams.put("paramOne", param1);
mParams.put("paramTwo", param2);
}
#Override
public Map<String, String> getParams() {
return mParams;
}
}
Evan Charlton was kind enough to make a quick example project to show us how to use volley.
https://github.com/evancharlton/folly/
CustomRequest is a way to solve the Volley's JSONObjectRequest can't post parameters like the StringRequest
here is the helper class which allow to add params:
import java.io.UnsupportedEncodingException;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
public class CustomRequest extends Request<JSONObject> {
private Listener<JSONObject> listener;
private Map<String, String> params;
public CustomRequest(String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.listener = reponseListener;
this.params = params;
}
public CustomRequest(int method, String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(method, url, errorListener);
this.listener = reponseListener;
this.params = params;
}
protected Map<String, String> getParams()
throws com.android.volley.AuthFailureError {
return params;
};
#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));
}
}
#Override
protected void deliverResponse(JSONObject response) {
// TODO Auto-generated method stub
listener.onResponse(response);
}
}
thanks to Greenchiu
This helper class manages parameters for GET and POST requests:
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
public class CustomRequest extends Request<JSONObject> {
private int mMethod;
private String mUrl;
private Map<String, String> mParams;
private Listener<JSONObject> mListener;
public CustomRequest(int method, String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(method, url, errorListener);
this.mMethod = method;
this.mUrl = url;
this.mParams = params;
this.mListener = reponseListener;
}
#Override
public String getUrl() {
if(mMethod == Request.Method.GET) {
if(mParams != null) {
StringBuilder stringBuilder = new StringBuilder(mUrl);
Iterator<Map.Entry<String, String>> iterator = mParams.entrySet().iterator();
int i = 1;
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
if (i == 1) {
stringBuilder.append("?" + entry.getKey() + "=" + entry.getValue());
} else {
stringBuilder.append("&" + entry.getKey() + "=" + entry.getValue());
}
iterator.remove(); // avoids a ConcurrentModificationException
i++;
}
mUrl = stringBuilder.toString();
}
}
return mUrl;
}
#Override
protected Map<String, String> getParams()
throws com.android.volley.AuthFailureError {
return mParams;
};
#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));
}
}
#Override
protected void deliverResponse(JSONObject response) {
// TODO Auto-generated method stub
mListener.onResponse(response);
}
}
Dealing with GET parameters I iterated on Andrea Motto' solution.
The problem was that Volley called GetUrl several times and his solution, using an Iterator, destroyed original Map object. The subsequent Volley internal calls had an empty params object.
I added also the encode of parameters.
This is an inline usage (no subclass).
public void GET(String url, Map<String, String> params, Response.Listener<String> response_listener, Response.ErrorListener error_listener, String API_KEY, String stringRequestTag) {
final Map<String, String> mParams = params;
final String mAPI_KEY = API_KEY;
final String mUrl = url;
StringRequest stringRequest = new StringRequest(
Request.Method.GET,
mUrl,
response_listener,
error_listener
) {
#Override
protected Map<String, String> getParams() {
return mParams;
}
#Override
public String getUrl() {
StringBuilder stringBuilder = new StringBuilder(mUrl);
int i = 1;
for (Map.Entry<String,String> entry: mParams.entrySet()) {
String key;
String value;
try {
key = URLEncoder.encode(entry.getKey(), "UTF-8");
value = URLEncoder.encode(entry.getValue(), "UTF-8");
if(i == 1) {
stringBuilder.append("?" + key + "=" + value);
} else {
stringBuilder.append("&" + key + "=" + value);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
i++;
}
String url = stringBuilder.toString();
return url;
}
#Override
public Map<String, String> getHeaders() {
Map<String, String> headers = new HashMap<>();
if (!(mAPI_KEY.equals(""))) {
headers.put("X-API-KEY", mAPI_KEY);
}
return headers;
}
};
if (stringRequestTag != null) {
stringRequest.setTag(stringRequestTag);
}
mRequestQueue.add(stringRequest);
}
This function uses headers to pass an APIKEY and sets a TAG to the request useful to cancel it before its completion.
Hope this helps.
This may help you...
private void loggedInToMainPage(final String emailName, final String passwordName) {
String tag_string_req = "req_login";
StringRequest stringRequest = new StringRequest(Request.Method.POST, "http://localhost/index", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Login Response: " + response.toString());
try {
JSONObject jsonObject = new JSONObject(response);
Boolean error = jsonObject.getBoolean("error");
if (!error) {
String uid = jsonObject.getString("uid");
JSONObject user = jsonObject.getJSONObject("user");
String email = user.getString("email");
String password = user.getString("password");
session.setLogin(true);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
Toast.makeText(getApplicationContext(), "its ok", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
System.out.println("volley Error .................");
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("tag", "login");
params.put("email", emailName);
params.put("password", passwordName);
return params;
}
};
MyApplication.getInstance().addToRequestQueue(stringRequest,tag_string_req);
}
For Future Readers
I love to work with Volley. To save development time i tried to write small handy library Gloxey Netwok Manager to setup Volley with my project. It includes JSON parser and different other methods that helps to check network availability.
Use ConnectionManager.class in which different methods for Volley String and Volley JSON request are available.
You can make requests of GET, PUT, POST, DELETE with or without header. You can read full documentation here.
Just put this line in your gradle file.
dependencies {
compile 'io.gloxey.gnm:network-manager:1.0.1'
}
Volley StringRequest
Method GET (without header)
ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, volleyResponseInterface);
How to use?
Configuration Description
Context Context
isDialog If true dialog will appear, otherwise not.
progressView For custom progress view supply your progress view id and make isDialog true. otherwise pass null.
requestURL Pass your API URL.
volleyResponseInterface Callback for response.
Example
ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
#Override
public void onResponse(String _response) {
/**
* Handle Response
*/
}
#Override
public void onErrorResponse(VolleyError error) {
/**
* handle Volley Error
*/
}
#Override
public void isNetwork(boolean connected) {
/**
* True if internet is connected otherwise false
*/
}
});
Volley StringRequest
Method POST/PUT/DELETE (without header)
ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, requestMethod, params, volleyResponseInterface);
Example
Use Method : Request.Method.POST
Request.Method.PUT
Request.Method.DELETE
Your params :
HashMap<String, String> params = new HashMap<>();
params.put("param 1", "value");
params.put("param 2", "value");
ConnectionManager.volleyStringRequest(this, true, null, "url", Request.Method.POST, params, new VolleyResponse() {
#Override
public void onResponse(String _response) {
/**
* Handle Response
*/
}
#Override
public void onErrorResponse(VolleyError error) {
/**
* handle Volley Error
*/
}
#Override
public void isNetwork(boolean connected) {
/**
* True if internet is connected otherwise false
*/
}
});
Bonus
Gloxey JSON Parser
Feel free to use gloxey json parser to parse your api response.
YourModel yourModel = GloxeyJsonParser.getInstance().parse(stringResponse, YourModel.class);
Example
ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
#Override
public void onResponse(String _response) {
/**
* Handle Response
*/
try {
YourModel yourModel = GloxeyJsonParser.getInstance().parse(_response, YourModel.class);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onErrorResponse(VolleyError error) {
/**
* handle Volley Error
*/
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
#Override
public void onClick(View view) {
//handle retry button
}
});
} else if (error instanceof AuthFailureError) {
} else if (error instanceof ServerError) {
} else if (error instanceof NetworkError) {
} else if (error instanceof ParseError) {
}
}
#Override
public void isNetwork(boolean connected) {
/**
* True if internet is connected otherwise false
*/
if (!connected) {
showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
#Override
public void onClick(View view) {
//Handle retry button
}
});
}
});
public void showSnackBar(View view, String message) {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
}
public void showSnackBar(View view, String message, String actionText, View.OnClickListener onClickListener) {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).setAction(actionText, onClickListener).show();
}
To provide POST parameter send your parameter as JSONObject in to the JsonObjectRequest constructor. 3rd parameter accepts a JSONObject that is used in Request body.
JSONObject paramJson = new JSONObject();
paramJson.put("key1", "value1");
paramJson.put("key2", "value2");
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,url,paramJson,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(jsonObjectRequest);
Related
I am not sure if this is the right approach to the following problem:
I have to record some GPS Data and store it in a JSON Array. This data is to be sent to the server to be stored in a database. The server is capable of handling a JSON Array of any length. The relevant code is:
public void onLocationChanged(final Location location) {
try{
JSONObject temp = new JSONObject();
temp.put("trackerid", prefs.getString("trackerid", "Some ID"));
temp.put("latitude", location.getLatitude());
temp.put("longitude", location.getLongitude());
Calendar time = Calendar.getInstance();
Date currentLocalTime = time.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-d hh:m:ss", Locale.ENGLISH);
temp.put("timestamp",sdf.format(currentLocalTime));
arrJ.put(temp);
}
catch (JSONException e){
log("Not able to format JSON" + ": "+ e.toString());
}
StringRequest sr = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//Code that verifies if the request is successfull and removes only the sent objects from the JSONArray.
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error){
//Code that Handles the error.
}
}){
#Override
protected Map<String, String> getParams(){
Map<String, String> params = new HashMap<>();
try {
params.put("data", json.put("data", arrJ).toString());
}catch (JSONException e){
e.printStackTrace();
}
return params;
}
};
queue.add(sr);
}
The problem I am facing is as follows: Once the GPSData has been recorded in the JSONArray, It is then picked up by the Network(Volley) Request thread and processed. Now because I don't know how long the request would take, I need to be able to get the sent Parameters in the getParams() function in the onResponse() function to be able to remove only the sent objects from the JSONArray to avoid duplication.
I am not sure if this is the correct implementation. If there is a better approach, I am definitely open to incorporating it into the app.
You can use this custom request ,
import com.android.volley.AuthFailureError;
import com.android.volley.Response;
import com.android.volley.toolbox.StringRequest;
import java.util.HashMap;
import java.util.Map;
/**
* #author Krish
*/
public class CustomRequest {
private Response.Listener<String> mOriginalListner;
private String requestData;
private StringRequest request;
public CustomRequest(int method, String json, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
this.requestData = json;
this.mOriginalListner = listener;
init(method, url, mListener, errorListener);
}
private Response.Listener<String> mListener = new Response.Listener<String>() {
#Override
public void onResponse(String response) {
mOriginalListner.onResponse(requestData);
}
};
private void init(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
this.request = new StringRequest(method, url, listener, errorListener) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
try {
params.put("data", requestData);
} catch (Exception e) {
e.printStackTrace();
}
return params;
}
};
}
public StringRequest build() {
return request;
}
}
and you can use the response to remove the send objects.
I am using volley library but when I use basic authentication then I do not got any response and also volley is not showing any error. I am also try HttpUrlConnection with Asyntask but I face same problem. Please provide solution this problem.
I also hit my api via Postman client, ARC and my api is working fine with these client.
MyJsonObjectRequest.java
public class MyJsonObjectRequest extends JsonRequest<JSONObject> {
private Priority priority = null;
//private Map<String, String> headers = new HashMap<String, String>();
public MyJsonObjectRequest(int method, String url, JSONObject jsonRequest, Listener<JSONObject> listener, ErrorListener errorListener) {
super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, errorListener);
}
public MyJsonObjectRequest(String url, JSONObject jsonRequest, Listener<JSONObject> listener,
ErrorListener errorListener) {
this(jsonRequest == null ? Method.GET : Method.POST, url, jsonRequest,
listener, errorListener);
}
#Override
public Priority getPriority() {
if (this.priority != null) {
return priority;
} else {
return Priority.NORMAL;
}
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
//Log.e("JSON"," AUTH CODE "+createBasicAuthHeader("MaS", "123456"));
return createBasicAuthHeader("username", "123456");
}
Map<String, String> createBasicAuthHeader(String username, String password) {
Map<String, String> headerMap = new HashMap<String, String>();
String credentials = username + ":" + password;
String encodedCredentials = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
headerMap.put("Content-Type", "application/json; charset=utf-8");
headerMap.put("Authorization", "Basic " + encodedCredentials);
return headerMap;
}
public void setHeader(String title, String content) {
// headers.put(title, content);
}
public void setPriority(Priority priority) {
this.priority = priority;
}
#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));
}
}
#Override
protected VolleyError parseNetworkError(VolleyError volleyError){
NetworkResponse response = volleyError.networkResponse;
if (response!=null)
{
Log.e("TAG"," VOLLEY ERROR1 "+response.statusCode);
}
if(volleyError.networkResponse != null && volleyError.networkResponse.data != null){
VolleyError error = new VolleyError(new String(volleyError.networkResponse.data));
Log.e("TAG"," VOLLEY ERROR "+error.toString());
volleyError = error;
}
return volleyError;
}
}
My MainActvity
public class JsonObjectActivity extends AppCompatActivity {
JsonObjectRequest gsonRequest;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_json_object);
textView = (TextView) findViewById(R.id.tv2);
try {
doingProcessJsonArray();
} catch (JSONException e) {
e.printStackTrace();
}
}
public void doingProcessJsonArray() throws JSONException {
// i am use local server like
String newUrl="http://myserver:8023/Users.svc/password_encrypt";
JSONObject params = new JSONObject();
params.put("PASSWORD", "12345655");
//params.put("domain", "http://samset.info");
gsonRequest =new JsonObjectRequest(Request.Method.POST,newUrl, params, successListener(), errorListener());
Constants.showProgressDialog(this, "Loading..");
//gsonRequest.setRetryPolicy(new DefaultRetryPolicy(6000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
// Start progressbar
// gsonRequest.setPriority(Request.Priority.IMMEDIATE);
Log.e("TAG"," request "+gsonRequest.toString());
VolleySingleton.getInstance(this).addToRequestQueue(gsonRequest, "volleyrequest");
}
private Response.ErrorListener errorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley","Error "+error.toString());
}
};
}
public Response.Listener successListener()
{
return new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response) {
Constants.dismissDialog();
Log.e("Volley","Responce "+response.toString());
textView.setText("JSONObject RESPONCE > "+response.toString());
}
};
}
}
postman screen shot
Hi I know voley call sending parameter using Map
for ex
private void SignInWithEmail() {
//email= String.valueOf(mEmail.getText());
//pass = String.valueOf(mPassword.getText());
String url = RequestUrls.getInstance().signInByEmail();
StringRequest mRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.v(TAG, "Login with email" + response);
try {
JSONObject jsonResponse = new JSONObject(response);
String code = jsonResponse.getString("code");
if (code == "1") {
JSONArray UserDetailArray = jsonResponse.getJSONArray("document");
Log.v("Login with email", UserDetailArray.toString());
JSONObject finalObject = UserDetailArray.getJSONObject(0);
String User_email = finalObject.getString("Email");
getUserByEmail(User_email);
} else {
Toast.makeText(getApplicationContext(), "Invalid Email or Password", Toast.LENGTH_SHORT).show();
mPassword.setText("");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.v(TAG, "Request for getUserByEmail Error: " + error.toString());
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Action", "GetUserByEmail");
//Log.v("Login", "Action Email for put: " + email);
params.put("UserName", email);
params.put("Password", pass);
return params;
}
};
VolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(mRequest);
}
but i have to send
this as parameter how to do that
{
"jsonrpc": "2.0",
"method": "signUp",
"id": "1",
"params": {
"email": "abc#gmail.com",
"fname": "abc",
"lname": "def",
"pwd": "123"
}
}
do i have to add header or any other method please suggest me.I am new in android development.
this the screen shot from postman chrome extension
please help me.
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.POST, url, json, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
});
you can send your json using the above code in the json paramter.
try
JSONObject jsonObject1 = new JSONObject();
try {
jsonObject1.put("email", "abc#gmail.com");
jsonObject1.put("fname", "abc");
jsonObject1.put("lname", "def");
jsonObject1.put("pwd", "123");
} catch (JSONException e) {
e.printStackTrace();
}
Map<String, String> postParam = new HashMap<>();
postParam.put("jsonrpc", "2.0");
postParam.put("method", "signUp");
postParam.put("id", "1");
postParam.put("params", jsonObject1.toString());
CustomRequest jsObjRequest = new CustomRequest(
Request.Method.POST,
URL,
postParam, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError arg0) {
}
});
mRequestQueue.add(jsObjRequest);
Happy code
import java.io.UnsupportedEncodingException;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
public class CustomRequest extends Request<JSONObject> {
private Listener<JSONObject> listener;
private Map<String, String> params;
public CustomRequest(String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.listener = reponseListener;
this.params = params;
}
public CustomRequest(int method, String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(method, url, errorListener);
this.listener = reponseListener;
this.params = params;
}
protected Map<String, String> getParams()
throws com.android.volley.AuthFailureError {
return params;
};
#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));
}
}
#Override
protected void deliverResponse(JSONObject response) {
// TODO Auto-generated method stub
listener.onResponse(response);
}
}
Use CustomRequest and pass your map in the argument.
Steps to Send Object/Model/POJO class to volley post request.
Step 1: Make sure your class should the parsable.
Step 2: Override the toString method in model class.
Step 3: Create map i.e Map<String, Object> params = new Map<String, Object>
();
JSONObject object = new JSONObject(classObject.toString())
params.put("key", object)
Step 4: Put the params with volley request.
I need to send a POST request to a server using the following JSON object format:
{"auth": {"tenantName": "<tenant>", "passwordCredentials": {"username": "<user>", "password": "<password>"}}}
to get an authentication token as response for subsequent requests:
{
access: {
token: {
issued_at: "2014-11-03T01:45:53.819103"
expires: "2014-11-03T02:45:53Z"
id: "686889ba4244432696aaac1d022f4973"
So far I'm just testing the connection with volley to see if I can get the proper response in a Toast:
public void loginRequest(){
String[] credentials = getSharedPrefs();
final String user = credentials[0];
final String pass = credentials[1];
final String url = credentials[2];
JSONObject login = new JSONObject();
JSONObject result = new JSONObject();
try {
JSONObject auth = login.getJSONObject("auth");
JSONObject tenantName = auth.getJSONObject("tenantName");
JSONObject passwordCredentials = auth.getJSONObject("passwordCredentials");
JSONObject username = passwordCredentials.getJSONObject("username");
JSONObject password = passwordCredentials.getJSONObject("password");
login.put("tenantName","");
login.put("username",user);
login.put("password",pass);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest getRequest = new JsonObjectRequest(Request.Method.POST, url, login,
new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response) {
// display response
// TO DO
Toast toast = Toast.makeText(Login.this,response.toString(),Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL,0,120);
toast.show();
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(Login.this, error.getMessage(), Toast.LENGTH_LONG).show();
}
}
){
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("tenantName", "");
params.put("username", user);
params.put("password", pass);
return params;
}
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Accept", "application/json");
params.put("Content-Type", "application/json");
return params;
}
};
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(getRequest);
}
}
However I'm getting the following error:
E/Volley﹕ [893] NetworkDispatcher.run: Unhandled exception java.lang.RuntimeException: Bad URL
java.lang.RuntimeException: Bad URL
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:147)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:110)
Caused by: java.net.MalformedURLException: Protocol not found:
at java.net.URL.<init>(URL.java:176)
at java.net.URL.<init>(URL.java:125)
at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:101)
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:110)
Any idea what I'm missing?
EDIT: I did some more digging and realised the error above was caused by a wrong getter on the string "url". I fixed that but now I get:
E/Volley﹕ [787] BasicNetwork.performRequest: Unexpected response code 400 for http://10.10.10.10:5000/v2.0/tokens
It seems the code is not sending JSON properly. For instance if I try to send anything other than aplication/json to the site using the Advanced Rest Client I also get 400 Bad Request
package com.example.wexindemo;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
public class JsonObjectPostRequest extends Request<JSONObject> {
private Map<String, String> mMap;
private String params;
private Listener<JSONObject> mListener;
public JsonObjectPostRequest(String url, Listener<JSONObject> listener,
ErrorListener errorListener, String params) {
super(Request.Method.POST, url, errorListener);
mListener = listener;
this.params = params;
}
public JsonObjectPostRequest(String url, Listener<JSONObject> listener,
ErrorListener errorListener, Map map) {
super(Request.Method.POST, url, errorListener);
mListener = listener;
mMap = map;
}
// #Override
// protected Map<String, String> getParams() throws AuthFailureError {
//
// return mMap;
//
// }
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String>();
headers.put("Charset", "UTF-8");
headers.put("Content-Type", "application/x-javascript");
headers.put("Accept-Encoding", "gzip,deflate");
return headers;
}
#Override
public byte[] getBody() throws AuthFailureError {
return params == null ? super.getBody() : params.getBytes();
}
#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));
}
}
#Override
protected void deliverResponse(JSONObject response) {
mListener.onResponse(response);
}
}
ps:You try to use this class to send a post request
I made it work using a String:
final String json = "{\"auth\": {\"tenantName\": \""+tnt+"\", \"passwordCredentials\": {\"username\": \""+user+"\", \"password\": \""+pass+"\"}}}";
JSONObject login = null;
try {
login = new JSONObject(json);
} catch (JSONException e) {
e.printStackTrace();
}
However I still would like to know how to do it programatically using JSONObject to get to know the proper syntax. Any takers?
I saw Google IO 2013 session about Volley and I'm considering switching to volley. Does Volley support adding POST/GET parameters to request? If yes, how can I do it?
For the GET parameters there are two alternatives:
First: As suggested in a comment bellow the question you can just use String and replace the parameters placeholders with their values like:
String uri = String.format("http://somesite.com/some_endpoint.php?param1=%1$s¶m2=%2$s",
num1,
num2);
StringRequest myReq = new StringRequest(Method.GET,
uri,
createMyReqSuccessListener(),
createMyReqErrorListener());
queue.add(myReq);
where num1 and num2 are String variables that contain your values.
Second: If you are using newer external HttpClient (4.2.x for example) you can use URIBuilder to build your Uri. Advantage is that if your uri string already has parameters in it it will be easier to pass it to the URIBuilder and then use ub.setQuery(URLEncodedUtils.format(getGetParams(), "UTF-8")); to add your additional parameters. That way you will not bother to check if "?" is already added to the uri or to miss some & thus eliminating a source for potential errors.
For the POST parameters probably sometimes will be easier than the accepted answer to do it like:
StringRequest myReq = new StringRequest(Method.POST,
"http://somesite.com/some_endpoint.php",
createMyReqSuccessListener(),
createMyReqErrorListener()) {
protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("param1", num1);
params.put("param2", num2);
return params;
};
};
queue.add(myReq);
e.g. to just override the getParams() method.
You can find a working example (along with many other basic Volley examples) in the Andorid Volley Examples project.
In your Request class (that extends Request), override the getParams() method. You would do the same for headers, just override getHeaders().
If you look at PostWithBody class in TestRequest.java in Volley tests, you'll find an example.
It goes something like this
public class LoginRequest extends Request<String> {
// ... other methods go here
private Map<String, String> mParams;
public LoginRequest(String param1, String param2, Listener<String> listener, ErrorListener errorListener) {
super(Method.POST, "http://test.url", errorListener);
mListener = listener;
mParams = new HashMap<String, String>();
mParams.put("paramOne", param1);
mParams.put("paramTwo", param2);
}
#Override
public Map<String, String> getParams() {
return mParams;
}
}
Evan Charlton was kind enough to make a quick example project to show us how to use volley.
https://github.com/evancharlton/folly/
CustomRequest is a way to solve the Volley's JSONObjectRequest can't post parameters like the StringRequest
here is the helper class which allow to add params:
import java.io.UnsupportedEncodingException;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
public class CustomRequest extends Request<JSONObject> {
private Listener<JSONObject> listener;
private Map<String, String> params;
public CustomRequest(String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.listener = reponseListener;
this.params = params;
}
public CustomRequest(int method, String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(method, url, errorListener);
this.listener = reponseListener;
this.params = params;
}
protected Map<String, String> getParams()
throws com.android.volley.AuthFailureError {
return params;
};
#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));
}
}
#Override
protected void deliverResponse(JSONObject response) {
// TODO Auto-generated method stub
listener.onResponse(response);
}
}
thanks to Greenchiu
This helper class manages parameters for GET and POST requests:
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import org.json.JSONException;
import org.json.JSONObject;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.toolbox.HttpHeaderParser;
public class CustomRequest extends Request<JSONObject> {
private int mMethod;
private String mUrl;
private Map<String, String> mParams;
private Listener<JSONObject> mListener;
public CustomRequest(int method, String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(method, url, errorListener);
this.mMethod = method;
this.mUrl = url;
this.mParams = params;
this.mListener = reponseListener;
}
#Override
public String getUrl() {
if(mMethod == Request.Method.GET) {
if(mParams != null) {
StringBuilder stringBuilder = new StringBuilder(mUrl);
Iterator<Map.Entry<String, String>> iterator = mParams.entrySet().iterator();
int i = 1;
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
if (i == 1) {
stringBuilder.append("?" + entry.getKey() + "=" + entry.getValue());
} else {
stringBuilder.append("&" + entry.getKey() + "=" + entry.getValue());
}
iterator.remove(); // avoids a ConcurrentModificationException
i++;
}
mUrl = stringBuilder.toString();
}
}
return mUrl;
}
#Override
protected Map<String, String> getParams()
throws com.android.volley.AuthFailureError {
return mParams;
};
#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));
}
}
#Override
protected void deliverResponse(JSONObject response) {
// TODO Auto-generated method stub
mListener.onResponse(response);
}
}
Dealing with GET parameters I iterated on Andrea Motto' solution.
The problem was that Volley called GetUrl several times and his solution, using an Iterator, destroyed original Map object. The subsequent Volley internal calls had an empty params object.
I added also the encode of parameters.
This is an inline usage (no subclass).
public void GET(String url, Map<String, String> params, Response.Listener<String> response_listener, Response.ErrorListener error_listener, String API_KEY, String stringRequestTag) {
final Map<String, String> mParams = params;
final String mAPI_KEY = API_KEY;
final String mUrl = url;
StringRequest stringRequest = new StringRequest(
Request.Method.GET,
mUrl,
response_listener,
error_listener
) {
#Override
protected Map<String, String> getParams() {
return mParams;
}
#Override
public String getUrl() {
StringBuilder stringBuilder = new StringBuilder(mUrl);
int i = 1;
for (Map.Entry<String,String> entry: mParams.entrySet()) {
String key;
String value;
try {
key = URLEncoder.encode(entry.getKey(), "UTF-8");
value = URLEncoder.encode(entry.getValue(), "UTF-8");
if(i == 1) {
stringBuilder.append("?" + key + "=" + value);
} else {
stringBuilder.append("&" + key + "=" + value);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
i++;
}
String url = stringBuilder.toString();
return url;
}
#Override
public Map<String, String> getHeaders() {
Map<String, String> headers = new HashMap<>();
if (!(mAPI_KEY.equals(""))) {
headers.put("X-API-KEY", mAPI_KEY);
}
return headers;
}
};
if (stringRequestTag != null) {
stringRequest.setTag(stringRequestTag);
}
mRequestQueue.add(stringRequest);
}
This function uses headers to pass an APIKEY and sets a TAG to the request useful to cancel it before its completion.
Hope this helps.
This may help you...
private void loggedInToMainPage(final String emailName, final String passwordName) {
String tag_string_req = "req_login";
StringRequest stringRequest = new StringRequest(Request.Method.POST, "http://localhost/index", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Login Response: " + response.toString());
try {
JSONObject jsonObject = new JSONObject(response);
Boolean error = jsonObject.getBoolean("error");
if (!error) {
String uid = jsonObject.getString("uid");
JSONObject user = jsonObject.getJSONObject("user");
String email = user.getString("email");
String password = user.getString("password");
session.setLogin(true);
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
Toast.makeText(getApplicationContext(), "its ok", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
System.out.println("volley Error .................");
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("tag", "login");
params.put("email", emailName);
params.put("password", passwordName);
return params;
}
};
MyApplication.getInstance().addToRequestQueue(stringRequest,tag_string_req);
}
For Future Readers
I love to work with Volley. To save development time i tried to write small handy library Gloxey Netwok Manager to setup Volley with my project. It includes JSON parser and different other methods that helps to check network availability.
Use ConnectionManager.class in which different methods for Volley String and Volley JSON request are available.
You can make requests of GET, PUT, POST, DELETE with or without header. You can read full documentation here.
Just put this line in your gradle file.
dependencies {
compile 'io.gloxey.gnm:network-manager:1.0.1'
}
Volley StringRequest
Method GET (without header)
ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, volleyResponseInterface);
How to use?
Configuration Description
Context Context
isDialog If true dialog will appear, otherwise not.
progressView For custom progress view supply your progress view id and make isDialog true. otherwise pass null.
requestURL Pass your API URL.
volleyResponseInterface Callback for response.
Example
ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
#Override
public void onResponse(String _response) {
/**
* Handle Response
*/
}
#Override
public void onErrorResponse(VolleyError error) {
/**
* handle Volley Error
*/
}
#Override
public void isNetwork(boolean connected) {
/**
* True if internet is connected otherwise false
*/
}
});
Volley StringRequest
Method POST/PUT/DELETE (without header)
ConnectionManager.volleyStringRequest(context, isDialog, progressDialogView, requestURL, requestMethod, params, volleyResponseInterface);
Example
Use Method : Request.Method.POST
Request.Method.PUT
Request.Method.DELETE
Your params :
HashMap<String, String> params = new HashMap<>();
params.put("param 1", "value");
params.put("param 2", "value");
ConnectionManager.volleyStringRequest(this, true, null, "url", Request.Method.POST, params, new VolleyResponse() {
#Override
public void onResponse(String _response) {
/**
* Handle Response
*/
}
#Override
public void onErrorResponse(VolleyError error) {
/**
* handle Volley Error
*/
}
#Override
public void isNetwork(boolean connected) {
/**
* True if internet is connected otherwise false
*/
}
});
Bonus
Gloxey JSON Parser
Feel free to use gloxey json parser to parse your api response.
YourModel yourModel = GloxeyJsonParser.getInstance().parse(stringResponse, YourModel.class);
Example
ConnectionManager.volleyStringRequest(this, false, null, "url", new VolleyResponse() {
#Override
public void onResponse(String _response) {
/**
* Handle Response
*/
try {
YourModel yourModel = GloxeyJsonParser.getInstance().parse(_response, YourModel.class);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onErrorResponse(VolleyError error) {
/**
* handle Volley Error
*/
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
#Override
public void onClick(View view) {
//handle retry button
}
});
} else if (error instanceof AuthFailureError) {
} else if (error instanceof ServerError) {
} else if (error instanceof NetworkError) {
} else if (error instanceof ParseError) {
}
}
#Override
public void isNetwork(boolean connected) {
/**
* True if internet is connected otherwise false
*/
if (!connected) {
showSnackBar(parentLayout, getString(R.string.internet_not_found), getString(R.string.retry), new View.OnClickListener() {
#Override
public void onClick(View view) {
//Handle retry button
}
});
}
});
public void showSnackBar(View view, String message) {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
}
public void showSnackBar(View view, String message, String actionText, View.OnClickListener onClickListener) {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).setAction(actionText, onClickListener).show();
}
To provide POST parameter send your parameter as JSONObject in to the JsonObjectRequest constructor. 3rd parameter accepts a JSONObject that is used in Request body.
JSONObject paramJson = new JSONObject();
paramJson.put("key1", "value1");
paramJson.put("key2", "value2");
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,url,paramJson,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(jsonObjectRequest);