How can I make my code a synchronous POST volley request? - java

I'm building a tracking app for exercise. As the gps updates every 1 second, the latitude and longitude is added to an array. At the end of the exercise, when you press save, below method is executed, sending all co-ordinates to a database. Because it's an asynchronous request, the co-ordinates don't get loaded into the database in correct order. How can I fix this so it will wait until each iteration of loop is complete or something like that. Thanks
/* Inserts the latitude and longitude points from the latitudeAndLongitudePoints ArrayList
into the latitudeandlongitudepoints table in db*/
private void insertLatitudeAndLongitudePoints(){
//iterates though array of co-ordinates, and adds to database
for(int loop=0; loop<latitudeAndLongitudePoints.size();loop++) {
final int index = loop;
StringRequest stringRequest = new StringRequest(Request.Method.POST,
"http://rrush01.lampt.eeecs.qub.ac.uk/insertLatitudeAndLongitudePoints.php",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "Error: " + error.getMessage(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Latitude", String.valueOf(latitudeAndLongitudePoints.get(index).latitude));
params.put("Longitude", String.valueOf(latitudeAndLongitudePoints.get(index).longitude));
params.put("User", AccountInfo.accountEmail);
return params;
}
};
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(stringRequest);
}
}

Add dependency for Volley library in your build.gradle.
compile 'com.android.volley:volley:1.0.0'
Volley is a network library which makes fast and easier to make HTTP Request for android application. Using Volley library we don’t need to create AsyncTask to make multiple API calls in volley there is RequestQueue where we can enqueue each request. Here in this example, We used Google place autocomplete API. We are going to make synchronous HTTP Request using volley. To make synchronous HTTP request make a RequestFuture object. And make JsonObjectRequest pass this parameter RequestMethod, URL, pass object of type Json and pass RequestFuture instance.
RequestFuture<JSONObject> requestFuture=RequestFuture.newFuture();
final String mURL = "https://maps.googleapis.com/maps/api/place/
autocomplete/json?key="+KEY+"&input=" + input;
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST,
mURL,new JSONObject(),requestFuture,requestFuture);
MySingleton.getInstance(mContext).addToRequestQueue(request);
Add your request in RequestQueue. Now, whenever the user makes an HTTP request each request added to RequestQueue.To get response object from the requestFuture we call get() method. And we also set a timeout of let’s say 10 seconds so we don’t block the UI thread indefinitely in case our request times out.
try {
JSONObject object= requestFuture.get(10,TimeUnit.SECONDS);
} catch (InterruptedException e|ExecutionException e|TimeoutException e) {
e.printStackTrace();
}
Hope this helps you to understand how we can use volley used to make the synchronous HTTP request

Related

How to properly write a volley callback

I am trying to write a volley get a request to fetch me all the users of my API. I have successfully done this, however, my function has stopped working. If I run my code now and attempt to fetch all the users, it will just return an empty array. If I try to fetch them one more time without stopping the run, it will return to me all of the users.
This is my function:
public ArrayList<User> getAllUsers(final VolleyCallBack callBack) {
requestQueue = Volley.newRequestQueue(this);
JsonArrayRequest arrayRequest = new JsonArrayRequest(
Request.Method.GET,
"http://ecoproduce.eu/api/User",
null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.e("Rest response", response.toString());
Gson gson = new Gson();
User user = new User();
for (int i = 0; i < response.length(); i++) {
try {
user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
} catch (JSONException e) {
e.printStackTrace();
}
allUsers.add(user);
}
callBack.onSuccess();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error response", error.toString());
}
}
);
requestQueue.add(arrayRequest);
return allUsers;
}
This is my callback interface:
public interface VolleyCallBack {
ArrayList<User> onSuccess();
}
This is how I call the function:
ArrayList<User> currentUsers;
currentUsers = getAllUsers(new VolleyCallBack() {
#Override
public ArrayList<User> onSuccess() {
Log.e("Bla", "ALL DONE!!!");
return allUsers;
}
});
I don't know what the problem is, this was working perfectly like an hour ago but for some reason, it has stopped. This is my first attempt at writing RESTful requests and I can't really pinpoint the error of my code.
SOLUTION:
Problem solved by making the changes suggested by Reaz Murshed and moving the getAllUsers call to the body of onCreate insted of it being within the onClick() function.
The getAllUsers function is returning allUsers immediately after putting a get request in a background thread. That being said, you are getting the user list when the background thread for your API was not finished fetching your user list and hence you are getting an empty list for the first time.
However, during the second time, you are having it, because the first API request fetched the users successfully and updated your allUsers list. So, actually you are not getting the user list from the second time API request, you are getting it from the request that was made previously.
To tackle this problem, do not return the allUsers from your getAllUsers function immediately after sending the API request. Wait for the API request to fetch the data for you and you already have a setup for success callback, where you should be able to get your desired user data.
Hence, you need to implement your onSuccess method in your Activity or Fragment or wherever you are calling the getAllUsers method, and perform necessary actions with the list of users on receiving a successful callback.
I would suggest modifying your callback function a little so that you can actually pass on the information that you fetched from the server.
public interface VolleyCallBack {
void onSuccess(ArrayList<User>);
}
And in the onResponse function of Volley callback, pass the user list that was fetched as follows.
callBack.onSuccess(allUsers);
I hope that helps!

How to play mp3 file using volley with async task?

Hello friends I am new in android I want play online mp3 file from url I used it async task for playing online mp3 file but problem is that it takes too much time for processing request I heard volley is best for this purpose now I used volley but when request send to server it block my main Ui thread while I heard volley itself manage aysc task and faster performance but in my case I did see anything like that please help how play audio from url faster and second without block main thread with help of volley here audio url and my code
"http://wpaorg.wordproject.com/bibles/app/audio/21/1/1.mp3"
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://wpaorg.wordproject.com/bibles/app/audio/21/"+booknumber+"/"+chapternumber+".mp3";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
Toast.makeText(ALLVERSE.this, ""+response, Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ALLVERSE.this, ""+error, Toast.LENGTH_SHORT).show();
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
when i tried send request it takes to much time and second block ui thread why?

How to form an URL in Background thread before using it with an API?

I am working with an API for the first time.
My need is that I need to form an URL with certain parameters out of which one parameter cannot be formed in the Main UI thread and has to be formed in the Background thread.
I am planning to use to volley library to post the GET request.
I am using the Needle library which helps in running background tasks. This is What I have tried till now.
Needle.onBackgroundThread().execute(new UiRelatedTask<String>() {
#Override
protected String doWork() {
return url = GetUrl();
}
#Override
protected void thenDoUiRelatedWork(String result1) {
Log.e("JSON", url);
final JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener() {
#Override
public void onResponse(Object response) {
Log.e("JSON", response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("JSON", error.toString());
}
});
RequestQueue queue = VolleyController.getInstance(Activity.this.getApplicationContext()).getRequestQueue();
queue.start();
queue.add(jsonObjectRequest);
}
});
But the Main problem is that After the GetUrl() method immediately the thenDoUiRelatedWork method is called hence the request is made using an Invalid URL as the URL will still be loading in the background and then when the loading of the URL is over I am logging the URL Which is right.
I cannot use an AysncTask as my app is already using three AsyncTaks and additionally two more could be activated by the user based on the feature he is using. And also the API request has to be done in various places (3-4 places) hence using an AsyncTask will not be suitable.
Can anyone help me to first form the URL fully in the Background and the use volley to post the GET request.

How to receive confirmation in Volley or Retrofit?

I want to post some data to a MySQL database. The server-side code will determine whether the data is valid and respond with that determination. Upon receiving this response, the application-side code must decide if it needs to try again or continue on. I have tried callbacks, RequestFuture, and spin-waiting, but it is starting to seem like this type of functionality is not possible with Volley (making decisions based on the server response). Has anyone else had success in implementing this type of functionality?
Main Thread
postCampaign(campaign);
if (//data was invalid) {
//do postCampaign(campaign) again
}
Main Thread
private void postCampaign(final Campaign campaign) {
campaign.setRoomCode("XXXXXXXX");
StringRequest request = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// I want to make a decision based on response
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
...
}
}
) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
// put data
return params;
}
};
NetworkController.getInstance(this).addToRequestQueue(request);
}
from server side, you need to grab the data send by your app. Then you need to check for validations like is the passed data empty/incorrect(incase of passwords check for it against the password in database if its the correct one or not).
In the server side validation of your data, if the data is successfully validated and updated in database then give a success response with proper response code or else if database updation is failed, then give an error response with proper error response code. You may pass these response as a json format to the client(or in whatever format you are comfortable parsing)
Now in the app side you may have a response callback method(available in retrofit/volley). From the response obtained in this callback check if it is a success response or failure response and make appropriate decisions for success/ failure cases

Java: Wait with main thread for response listener in extra method

So, I'm writing an android app. During OnCreate() of an activity, I request some JSONObjects via HTTP GET. That method has a response listener that, well, does something when it gets a JSONObject. In the OnCreate-method, I need to use the response, so can I somehow set it up so that the OnCreate method waits until the response listener does it's job?
Do I have to use multithreading? Here's the code I'm talking about:
Here's the call in OnCreate():
...
// Instantiate the RequestQueue.
final RequestQueue queue = Volley.newRequestQueue(this);
executeJson(QUERY_URL);
System.out.println(jsonresponse);
...
Here's the called method:
private void executeJson(String url) {
SharedPreferences prefs = this.getSharedPreferences("AppPref", MODE_PRIVATE);
final String token = prefs.getString("token", null);
RequestQueue queue = Volley.newRequestQueue(this);
Map<String, String> params = new HashMap<String, String>();
System.out.println(token);
params.put("access_token", token);
CustomRequest jsonRequest = new CustomRequest(url, params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
jsonresponse = response;
}
}, this.createRequestErrorListener());
System.out.println(jsonRequest);
queue.add(jsonRequest);
}
I realize that a simple Thread.Sleep() would, well, make my app go to sleep entirely, so that can't be the solution.
The intention of this activity is to be a "Loading Activity" - It pops up once the user wants to access his data and creates an intent to the data activity, destroying itself after the data is loaded.
Yes, you need to do the request in a background thread. Use an AsyncTask, or other method. You do not want to do an arbitrarily long running request on the UI thread, nor 'pause' the UI thread to wait for the request to return. Read Android Processes and Threads for more info using threads in Android.

Categories

Resources