I am using Volley to post some data in a server.
private void checkLeague(final String username, final String password) {
String tag_json_obj = "json_obj_req";
final HashMap<String, String> postParams = new HashMap<String, String>();
postParams.put("username", username);
postParams.put("password", password);
Response.Listener<JSONObject> listener;
Response.ErrorListener errorListener;
final JSONObject jsonObject = new JSONObject(postParams);
final JsonObjectRequest jsonObjReq = new JsonObjectRequest(AppConfig.URL_CHECK_LEAGUE, jsonObject,
new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
if (response.getString("status").equals("fail")) {
checkLeader(username,password);
} else if (response.getString("status").equals("success")) {
deleteSharedPreferences();
text.setText("");
//timer.setText("League starts in:");
leagueCreation.setVisibility(View.GONE);
leagueInvitation.setVisibility(View.VISIBLE);
listView.setVisibility(View.VISIBLE);
readCheckLeagueSuccessfullData(response);
compareLeader();
dateFormatter();
setLeagueName();
getLeagueMembers(leagueId, username, password);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Bundle b = new Bundle();
b.putString("team_name", teamName);
b.putString("team_leader", teamLeader);
Intent intent = new Intent(League.this, UserDetails.class);
intent.putExtra("players_bundle", b);
startActivity(intent);
}
});
leagueInvitation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(League.this, LeagueInvitation.class);
i.putExtra("leagueId", leagueId);
i.putExtra("leagueName", leagueNameDb);
startActivity(i);
}
});
CounterClass counter = new CounterClass(leagueStartDiff, 1000);
counterTwoWeeks = new CounterClass1(leagueTwoWeeks, 1000);
counter.start();
}
} catch (JSONException e) {
Log.e("TAG", e.toString());
}
//pDialog.dismiss();
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//VolleyLog.d("TAG", "Error: " + error.getMessage());
//pDialog.dismiss();
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq,
tag_json_obj);
VolleySingleton.getInstance(getApplicationContext()).
addToRequestQueue(jsonObjRequest);
}
I put a breakpoint in this line
final JsonObjectRequest jsonObjReq = ...
to check if the data username,password in this case are basically going to the server. The problem is that I get this response which I don't like it very much.
[ ] http://.../..._..._check.php 0x8237d9fb NORMAL null
I should had got something like this from the debugger for the post request.
{
"username":"...",
"password":"..."
}
But I don't know why I get the null thing in my json request! It was working fine before. Maybe the link is broken?
Thank you.
Related
This question already has answers here:
Can I do a synchronous request with volley?
(8 answers)
Closed 4 years ago.
I have written a function that makes an HTTP request and the response stores in a Bundle to subsequently initialize an activity.
public static void communicate(final Context context, String url, final String typeResponse, final Intent intent) {
RequestQueue queue = Volley.newRequestQueue(context);
RequestFuture<String> future = RequestFuture.newFuture();
StringRequest stringRequest = new StringRequest(Request.Method.POST, BASE_URL + url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//Toast.makeText(context, response, Toast.LENGTH_SHORT).show();
Bundle bundle = new Bundle();
switch (typeResponse) {
case "text":
bundle.putString("response", response);
break;
case "json":
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray names = jsonObject.names();
for (int i = 0; i < names.length(); i++) {
//Toast.makeText(context, names.getString(i), Toast.LENGTH_SHORT).show();
bundle.putString(names.getString(i), jsonObject.getString(names.getString(i)));
}
} catch (JSONException e) {
e.printStackTrace();
}
break;
}
intent.putExtras(bundle);
context.startActivity(intent);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "error", Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("test", "hi!!");
return params;
}
};
queue.add(stringRequest);
}
But I want return the Bundle object for use that function like this:
Bundle myBundle = communicate('httl://qwe.asd', 'json')
How can I to modifier my function?
Thanks.
Volley request are asynchronous, so i recommend you put inner your onResponse other function to be process your bundle.
As well, you can create an interface to send your response in other place. Something like this
interface
public interface onResponseCallback {
void onResponse(Bundle bundle);
}
activity
public MyActivity extends AppCompatActivity implements onResponseCallback{
public void onCreate(Bundle....){
MyRequest myrequest = new MyRequest(this);
..}
public void onResponse(Bundle bundle){
//bundle argument is your response from request,
// do some with your response
Intent intent = new Intent....
intent.putExtras(bundle);
startActivity(intent);
}
}
Request class
public class MyRequest{
OnResponseCallback onResponseCallback= null;
public MyRequest(onResponseCallback onResponseCallback)
this.onResponseCallback = onResponseCallback;
}
public void communicate(final Context context, String url, final String typeResponse, final Intent intent) {
RequestQueue queue = Volley.newRequestQueue(context);
RequestFuture<String> future = RequestFuture.newFuture();
StringRequest stringRequest = new StringRequest(Request.Method.POST, BASE_URL + url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//Toast.makeText(context, response, Toast.LENGTH_SHORT).show();
Bundle bundle = new Bundle();
switch (typeResponse) {
case "text":
bundle.putString("response", response);
break;
case "json":
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray names = jsonObject.names();
for (int i = 0; i < names.length(); i++) {
//Toast.makeText(context, names.getString(i), Toast.LENGTH_SHORT).show();
bundle.putString(names.getString(i), jsonObject.getString(names.getString(i)));
}
} catch (JSONException e) {
e.printStackTrace();
}
break;
}
onResponseCallback.onResponse(bundle);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "error", Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("test", "hi!!");
return params;
}
};
queue.add(stringRequest);
}
}
and if you dont like nothing of this, maybe you can use constants or put in sharedpreferences to save your bundle object.
I hope that helps you.
I use the volley framework for my controllers in an android application
One of my controllers is as below:
public class LoginApi extends AppCompatActivity {
private static final String LOGIN_URL = "example"
private static final int timeOutInMs = 10000;
private static final int numberOfTries = 1;
public LoginApi() {
}
public void doLogin(final Context context, JSONObject jsonObject) {
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, LOGIN_URL, jsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
User user=new User();
try {
user.setAccessToken(response.getString("access_token"));
user.setExpireToken(response.getString("expires_in"));
user.setRefreshToken(response.getString("refresh_token"));
user.setTokenType(response.getString("token_type"));
Intent intent=new Intent(context,MenuCustomer.class);
Gson myGson=new Gson();
String myJson = myGson.toJson(user);
intent.putExtra("myjson", myJson);
context.startActivity(intent);
} catch (JSONException e) {
e.printStackTrace();
}
Log.d("", "");
Toast.makeText(context, "Successfull login", Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("", "");
Toast.makeText(context, "Please enter a valid email and password", Toast.LENGTH_SHORT).show();
}
}) {
#Override
public Map<String, String> getHeaders() {
Map<String, String> map = new HashMap<>();
map.put("Accept", "application/json");
map.put("Content-Type", "application/json");
return map;
}
};
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(timeOutInMs, numberOfTries, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
Singleton.getmInstance(context).addToRequestQueue(jsonObjectRequest);
}
}
I have tried to make mock classes (FakeHttpStack,FakeRequestQueue) and I tried to make tests from mock volley classes from here
I cant find a solution to unit test my class.
I am trying to hit multiple request using Volley and i am getting response for all the request. my problem is how to identify the response is belong to which API.
mQueue = CustomVolleyRequest.getInstance(this.getApplicationContext())
.getRequestQueue();
final CustomJSONObjectrequest jsonRequest = new CustomJSONObjectrequest(Request.Method
.GET, url,
new JSONObject(), this, this); //
jsonRequest.setTag(REQUEST_TAG);
final CustomJSONObjectrequest jsonRequest2 = new CustomJSONObjectrequest(Request.Method
.GET, url2,
new JSONObject(), this, this);
jsonRequest2.setTag(REQUEST_TAG);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mQueue.add(jsonRequest);
mQueue.add(jsonRequest2); // Both the request will have different API request
}
});
}
#Override
public void onErrorResponse(VolleyError error) {
mTextView.setText(error.getMessage());
}
#Override
public void onResponse(Object response) {
// How to identify, which response is belong to which api request
mTextView.setText("Response is: " + response);
}
Create a Generic Volley class and a Interface, Use the interface to get success and failure responds.
Step 1 Create a separate Volley class
Step 2 Create a interface for accessing the response from volley class
Step 3 create new object for
the class and send required parameters
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this(interfcae), "Submit", url, params);
Context of the class
Interface for sending Success and failure responds
Type of request to identify on success
url (mandatory)
Param (optional) for GET no need
Generic volley class
public class PostVolleyJsonRequest {
private String type;
private Activity act;
private VolleyJsonRespondsListener volleyJsonRespondsListener;
private String networkurl;
private JSONObject jsonObject = null;
private JSONObject params;
public PostVolleyJsonRequest(Activity act, VolleyJsonRespondsListener volleyJsonRespondsListener, String type, String netnetworkUrl,JSONObject params) {
this.act = act;
this.volleyJsonRespondsListener = volleyJsonRespondsListener;
this.type = type;
this.networkurl = netnetworkUrl;
this.params = params;
sendRequest();
}
private void sendRequest() {
Log.d("url", "url" + networkurl);
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,networkurl,params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e("response", "response " + response);
volleyJsonRespondsListener.onSuccessJson(response, type);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
NetworkResponse response = error.networkResponse;
Log.e("response", "response " + response);
if (response != null) {
int code = response.statusCode;
String errorMsg = new String(response.data);
Log.e("response", "response" + errorMsg);
try {
jsonObject = new JSONObject(errorMsg);
} catch (JSONException e) {
e.printStackTrace();
}
String msg = jsonObject.optString("message");
volleyJsonRespondsListener.onFailureJson(code, msg);
} else {
String errorMsg = error.getMessage();
volleyJsonRespondsListener.onFailureJson(0, errorMsg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
jsObjRequest.setRetryPolicy(new DefaultRetryPolicy(
600000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
RequestQueue requestqueue = Volley.newRequestQueue(act);
requestqueue.add(jsObjRequest);
}
}
Use the interface to get responds message
public interface VolleyJsonRespondsListener {
public void onSuccessJson(JSONObject result, String type);
public void onFailureJson(int responseCode, String responseMessage);
}
In your class where you want to include multiple request
public class TestVolley extends AppCompatActivity implements VolleyJsonRespondsListener{
//Your class code goes here
//network request
try {
//parameters
//Context,Interface,Type(to indentify your responds),URL,parameter for your request
//request 1
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this, "Submit", url, params);
//request 2
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this, "AccessData", url_2, params_2);
} catch (Exception e) {
e.printStackTrace()
}
//Methods from Interface
#Override
public void onSuccessJson(JSONObject result, String type) {
//Based on the Type you send get the responds and parse it
switch (type) {
case "Submit":
try {
parseSubmit(result);
} catch (Exception e) {
e.printStackTrace();
}
break;
case "AccessData":
try {
parseAccessData(result);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
You can do something like this for a single request. Same can be applied to the second request. This way you know which request is giving you the response.
final CustomJSONObjectrequest jsonRequest = new CustomJSONObjectrequest(Request.Method
.GET, url,
new JSONObject(), this, new Response.Listener<Object>() {
#Override
public void onResponse(Object response) {
// How to identify, which response is belong to which api request
mTextView.setText("Response is: " + response);
});
EDITED :
You can start with making an interface like :
public interface VolleyResponse {
void onResponse(JSONObject object, String tag);
void onError(VolleyError error, String tag);
}
Then you can make a custom handler for volley request like:
public class CustomJSONObjectRequest implements Response.Listener<JSONObject>, Response.ErrorListener {
private VolleyResponse volleyResponse;
private String tag;
private JsonObjectRequest jsonObjectRequest;
public CustomJSONObjectRequest(int method, String url, JSONObject jsonObject, String tag, VolleyResponse volleyResponse) {
this.volleyResponse = volleyResponse;
this.tag= tag;
jsonObjectRequest = new JsonObjectRequest(method, url, jsonObject, this, this);
}
#Override
public void onResponse(JSONObject response) {
volleyResponse.onResponse(response, tag);
}
#Override
public void onErrorResponse(VolleyError error) {
volleyResponse.onError(error, tag);
}
public JsonObjectRequest getJsonObjectRequest() {
return jsonObjectRequest;
}
}
And to call it in your class use it like:
CustomJSONObjectRequest request1 = new CustomJSONObjectRequest(Request.Method.GET, url,
new JSONObject(), "YOUR REQUEST TAG", this);
Make sure to let your class implement the VolleyResponse interface that will get you the response and your tag.
#Override
public void onResponse(JSONObject object, String tag) {
Log.i("Response :", object.toString() + " " + tag);
}
#Override
public void onError(VolleyError error, String tag) {
}
To add the request to the volley queue you can use:
mQueue.add(request1.getJsonObjectRequest());
PS : this code is not tested but it should work.
This is my Arraylist which I get from the previous fragment,
listoftags = getArguments().getParcelableArrayList("data");
It works well. Now I have to send this with some parameters like below:
public void volleyJsonObjectRequest(final String SessionID , final String CustomerID, final String ServiceState , final String ServiceID, final String Address, final String PaymentMode, final String CustomerComments , final ArrayList Items){
String REQUEST_TAG = "volleyJsonObjectRequest";
// POST parameters
CustomRequest request = new CustomRequest(Request.Method.POST, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// Toast.makeText(SignActivity.this, response.toString(), Toast.LENGTH_SHORT).show();
Log.d("response",""+response.toString());
/* String status = response.optString("StatusMessage");
String actionstatus = response.optString("ActionStatus");
Toast.makeText(getActivity(), ""+status, Toast.LENGTH_SHORT).show();
if(actionstatus.equals("Success"))
{
// Intent i = new Intent(SignActivity.this, LoginActivity.class);
// startActivity(i);
// finish();
}*/
dismissProgress();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), "Error."+error.toString(), Toast.LENGTH_SHORT).show();
Log.d("response",""+error.toString());
dismissProgress();
}
}) {
/* #Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=UTF-8";
}*/
public String getBodyContentType()
{
return "application/json; charset=utf-8";
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
JSONArray jsArray = new JSONArray(listoftags);
params.put("SessionID", SessionID);
params.put("CustomerID", CustomerID);
params.put("ServiceState", ServiceState);
params.put("ServiceID", ServiceID);
params.put("Address", Address);
params.put("PaymentMode",PaymentMode);
params.put("CustomerComments",CustomerComments);
params.put("Items",jsArray.toString());
return params;
}
};
AppSingleton.getInstance(getActivity().getApplicationContext())
.addToRequestQueue(request, REQUEST_TAG);
}
but it getting error to me I want to send it like
// server side //
{
"SessionID":"9lm5255sg0ti9",
"CustomerID":"9",
"ServiceState":"Karnataka",
"ServiceID":"3",
"Address":"sfaff",
"PaymentMode":"cash",
"CustomerComments":"this is fine",
"Items":[
{
"ItemId":1,
"Cost":6777,
"Quantity":33333
}
]
}
How can send arraylist, with other strings, as raw data using volley on server.
JsonObjectRequest can be used to execute rest api using json as input.
JsonObject jobj = new JsonObject();
jobj.put("key","value");
jobj.put("key","value");
jobj.put("key","value");
jobj.put("key","value");
JsonObjectRequest request = new JsonObjectRequest(requestURL, jobj, new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response) {
}
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
}
});
*Now add this request in request queue of volley.*
Here jobj is containing input parameters. It can contain even json array inside a JsonObject. Let me know in case of any query.
Rather then volley try retrofit. Make pojo model of your object you want to send, you can make that from pojo classes from https://www.jsonschema2pojo.org the send the whole object on restapi
// try the request //
try {
REQUEST QUEUE
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
String URL = url;
JSONObject jsonBody = new JSONObject();
JSONObject jsonObject = new JSONObject();
JSONArray jsonArray = new JSONArray();
Iterator itr = listoftags.iterator();
while(itr.hasNext()){
AddRowItem ad=(AddRowItem)itr.next();
jsonObject.put("ItemId:",1);
jsonObject.put("Cost:",ad.getPrices());
jsonObject.put("Quantity:",ad.getQty());
// Log.d("ItemId:",""+1+" "+"Cost:"+ad.getPrices()+" "+"Quantity:"+ad.getQty());
}
jsonArray.put(jsonObject);
JSON VALUES PUT
jsonBody.put("SessionID", "9kp0851kh6mk3");
jsonBody.put("CustomerID", "9");
jsonBody.put("ServiceState", "Karnataka");
jsonBody.put("ServiceID", "3");
jsonBody.put("Address", "Address Demo");
jsonBody.put("PaymentMode", "cost");
jsonBody.put("CustomerComments", "Android Volley Demo");
jsonBody.put("Items", jsonArray);
final String requestBody = jsonBody.toString();
Log.d("string ---- >",""+requestBody);
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i("VOLLEY", response);
showToast("get value"+response.toString());
try {
JSONObject jObj = new JSONObject(response);
String action = jObj.get("ActionStatus").toString();
String status = jObj.getString("StatusMessage");
{"ActionStatus":"Success","StatusMessage":"Order Created","RefIDName":"OrderID","RefIDValue":19}
showToast("get value"+action);
}
catch (JSONException e)
{
showToast("get error"+e.toString());
Log.d("errorissue",""+e.toString());
}
dismissProgress();
}
}, new Response.ErrorListener() {
// error response //
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.toString());
showToast("get error"+error.toString());
dismissProgress();
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
};
requestQueue.add(stringRequest);
} catch (JSONException e) {
e.printStackTrace();
dismissProgress();
}
}
}
// THIS IS THE WAY ISSUE RESLOVED //
THANKS EVERYONE ...
In my app I have an Activity LoginUserActivity that contains a button perform a connection to a web-server using JSONObject request and Volley. If the login is successfull will be launched another activity, but if it isn't I need to re-enable the button.
LoginUserActivity
public void OnLoginUtente(View view) {
final String mail = etMail.getText().toString();
final String pw = etPassword.getText().toString();
bLogin.setEnabled(false);
DBConnection connection = new DBConnection(mail, pw, getApplicationContext());
connection.doLogin();
}
doLogin()
public void doLogin() {
JSONObject obj = new JSONObject();
try {
obj.put("type", type);
obj.put("email", email);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, URL, obj,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
Toast.makeText(context, response.getString("Status"), Toast.LENGTH_SHORT).show();
if (response.getString("Esito").equals("true")) {
intent = new Intent(context, MainUtente.class);
context.startActivity(intent);
}else{
//I think I've to put something here
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
);
jsonObjectRequest.setShouldCache(false);
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.getCache().clear();
requestQueue.add(jsonObjectRequest);
}
I've tried different things, such as make doLogin() return a boolean and then re-enable the button from the activity or try to inflate the layout of the calling activity in the else, but neither of these worked. If possible I'd like to keep the doLogin() method void and without parameters.
LoginUserActivity
public void OnLoginUtente(View view) {
final String mail = etMail.getText().toString();
final String pw = etPassword.getText().toString();
DBConnection connection = new DBConnection(mail, pw, getApplicationContext());
connection.doLogin(this);
}
public void disableLoginButton()
{
bLogin.setEnabled(false);
}
doLogin
public void doLogin(final LoginActivity activity) {
JSONObject obj = new JSONObject();
try {
obj.put("type", type);
obj.put("email", email);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, URL, obj,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
Toast.makeText(context, response.getString("Status"), Toast.LENGTH_SHORT).show();
if (response.getString("Esito").equals("true")) {
new Handler(Looper.getMainLooper()).post(new Runnable(){
public void run() {
activity.disableLoginButton();
}
);
activity.disableLoginButton();
intent = new Intent(context, MainUtente.class);
context.startActivity(intent);
}else{
//I think I've to put something here
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
);
jsonObjectRequest.setShouldCache(false);
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.getCache().clear();
requestQueue.add(jsonObjectRequest);
}
You may replace new Handler(Looper.getMainLooper()).post(runnable) with activity.runOnUiThread(runnable)