I've searched a lot about this but can't find any solution. I have been using Volley for a long time to handle my network communication. Recently I decided to use a SyncAdapter to sync my data to the server. Inside the onPerformSync() method, I thought I'll use Volley to send the data to the server as its very easy with Volley to make GET, POST requests.
Problem - SyncAdapter and Volley both use their own seperate threads. So when I initiate a Volley request from inside the onPerformSync() method, the SyncAdapter does not wait for the Volley request to complete and finishes the sync before the onResponse() or onErrorResponse() callback of Volley is received. I need to make further network calls inside the SyncAdapter after first call returns successfully.
Example Code -
#Override
public void onPerformSync(Account account, Bundle extras, String authority,
ContentProviderClient provider, SyncResult syncResult) {
JsonObjectRequest jReq = new JsonObjectRequest(Method.POST, url, data,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i(TAG, "response = " + response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "error = " + error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(jReq);
//onPerformSync() exits before request finished
}
Question - So how do I make the SyncAdapter to wait until the network response is received by Volley?
Make a synchronous volley request.
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(URL, null, future, future);
requestQueue.add(request);
and then use:
try {
JSONObject response = future.get(); // this will block (forever)
} catch (InterruptedException e) {
// exception handling
} catch (ExecutionException e) {
// exception handling
}
Code from: Can I do a synchronous request with volley?
Related
I am learning about Volley and I don't know why the response from GET method is coming as a single char -> [.
I am using this method to get the JSON response:
public void getJsonMethod() {
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
// String url = "https://www.w3schools.com/js/myTutorials.txt";
String url = "http://www.google.com"; // with this url I am getting response
// Request a string response from the provided URL.
final StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println("Response is: " + response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("Response is not good" + error.getMessage());
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
When I am using this link I do get a response but when I try to use some link that contains nothing but JSON like this one my response it "[".
I am calling this method from Activity like this:
GetJsonClass getJson = new GetJsonClass(this);
getJson.getJsonMethod();
Any ideas on what am I doing wrong here?
Answer + code
If anyone will start using Volley maybe this can help him :
as David Lacroix said in his answer, I called stringRequest and notJsonArrayRequest.
Here is how it should have been:
public void getJsonMethod() {
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
String url = "your url";
JsonArrayRequest jsonObjectRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
System.out.println("this is response good" + response);
}
}, new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("this is response bad" + error);
}
});
queue.add(jsonObjectRequest);
}
See https://developer.android.com/training/volley/request
StringRequest. Specify a URL and receive a raw string in response. See Setting Up a Request Queue for an example.
JsonObjectRequest and JsonArrayRequest (both subclasses of JsonRequest). Specify a URL and get a JSON object or array (respectively) in response.
You should be using a JsonArrayRequest
myTutorials.txt is being served with status code 304 (no proper suffix and MIME type either):
304 Not Modified. If the client has performed a conditional GET request and access is allowed, but the document has not been modified, the server SHOULD respond with this status code. The 304 response MUST NOT contain a message-body, and thus is always terminated by the first empty line after the header fields.
In other terms, what the browser may display is not neccessarily the same what the server has sent. eg. GSON would accept that JSON only with option lenient enabled, because the array has no name.
see RFC 2616.
I have the following code which works to make a call and receives xml.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Do something with the response
Log.e(TAG, "response from RRSendCarerLocation = " + response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Handle error
Log.e(TAG, "error: RRSendCarerLocation = " + error);
}
});
rq.add(stringRequest);
.
The problem i have is, this works fine when called from an Activity but i want to use Volley from an IntentService. An intentService destroys itself after the work is done, so the Volley callbacks never retreive the response.
one solution i have found would be to use RequestFuture and call .get() to block the thread. i have an example below that i found here.
Can I do a synchronous request with volley?
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(URL, new JSONObject(), future, future);
requestQueue.add(request);
try {
return future.get(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// exception handling
} catch (ExecutionException e) {
// exception handling
} catch (TimeoutException e) {
// exception handling
}
.
I don't want to use JSON as the server returns xml. i've looked at the StringRequest class but i cannot see anything that supports a RequestFuture.
http://griosf.github.io/android-volley/com/android/volley/toolbox/StringRequest.html
Is there anyway to use the StringRequest code to return xml using the blocking functionality of RequestFuture
thanks
This is in case you did not find an optimum solution or for any people who come across this post with the same question. If you want to use StringRequest with FutureRequest you can try out the solution below.
// Setup a RequestFuture object with expected return/request type
RequestFuture<String> future = RequestFuture.newFuture();
// organize your string request object
StringRequest request = new StringRequest(url, future, future);
// add request to queue
VolleySingleton.getInstance(context).addToRequestQueue(request);
try {
// Set an interval for the request to timeout. This will block the
// worker thread and force it to wait for a response for 60 seconds
// before timing out and raising an exception
String response = future.get(60, TimeUnit.SECONDS);
// Do something with the response
Log.e(TAG, "response from RRSendCarerLocation = " + response);
return Result.success();
} catch (InterruptedException | TimeoutException | ExecutionException e) {
e.printStackTrace();
return Result.retry();
}
I use Retrofit for this types of requests. It is very easy to use and allows you to make both types of requests (sync and unsync)
http://square.github.io/retrofit/
I am using Volley JsonObjectRequest to get data from server.
code snippet:
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println("Response: " + response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
}
});
But I am getting same JSONObject response every time on mobile data connection.
Note: It's work perfectly on WiFi connection.
Is anyone facing this issue ? any solution ?
#BNK request.setShouldCache(false); worked for me. It's issue of volley cache management.
I assume that, when a request is sent:
It would hit the cache first and send that to onResponse
then when the results come through from the remote server it would provide it to the onResponse
If you use any of the default Request classes implemented in volley(e.g. StringRequest, JsonRequest, etc.), then call setShouldCache(false) right before adding the request object to the volley RequestQueue
request.setShouldCache(false);
myQueue.add(request);
You can also set expiration policy for cache.
See this answer for more details
i am trying to consume a MVC 4 api from my android application
i am using Volley library and it work fine to get data from server
the problem is when i try to send data to the web service which i understand it should be done by using post Method and JsonObjectRequest
my method in MVC Api is :
public class ItemController : ApiController
{
public IEnumerable<string> Post(List<string> val)
{
return val;
}
}
and for volley :
String tag_string_req = "req_login";
Map<String, String> params = new HashMap<>();
params.put("email", "S#b.Com");
params.put("username", "basheq");
JsonObjectRequest req = new JsonObjectRequest(Method.POST ,
AppConfig.URL_REGISTER, new JSONObject(params),new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject jsonObject) {
Log.d(TAG, "Login Response: " + jsonObject.toString());
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Login Error: " + error.getMessage());
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(req, tag_string_req);
but i keep getting null in response and it look like the api doesn't parse the parameter .
what is wrong ?? , and is this the proper way to do it or is there a better way ??
The main problem was that i was setting list as a parameter which for some reason does not work
the solution was by wrapping the input parameter into a class and of course change the json structure to correspond to that
I'm using Volley library to access my server data.Volley has inbuilt caching function.I tried to use that as follows.this out put "CACHED RESPONSE". but i don't know how to access the cached data.
void initHttpCall(){
RequestQueue queue = Volley.newRequestQueue(mcontext);
UOBRequest<RateData> myReq = new UOBRequest<RateData>(Method.GET,
Constants.GET_RATES,
RateData.class,
mlistner,
createMyReqErrorListener()){
#Override
public Map<String, String> getHeaders(){
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", getToken());
headers.put("Accept","application/json" );
return headers;
}
};
myReq.setShouldCache(true);
if(queue.getCache().get(Constants.GET_RATES)!=null){
System.out.println("CACHED RESPONSE");
}else{
queue.add(myReq);
}
}
}
This is my response listner and want to get RateData object here.
new Response.Listener<RateData>() {
#Override
public void onResponse(RateData rateData) {
setupCurrencyPager(rateData);
setLastUpdatedTime();
}
});
You misunderstood how Volley's caching system works. The beauty of it is that as a user of Volley, you are unaware of where the response is coming from.
When you add a new request to the RequestQueue, Volley checks if that request already has a cached response. If it does, and that response has not expired yet, it is returned immediately. Otherwise, it goes outside to the network, retrieves the response, caches it and returns it to you.
You don't need that last if statement, simply add it to the queue and Volley will take care of the rest.
try the following code.it will help you sure.
please create a request which you want to pass to server.
JSONObject request = new JSONObject();
request.put("user","user2");
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, url, request, new Response.Listener() {
#Override
public void onResponse(JSONObject response) {
// TODO Auto-generated method stub
Log.v("response:-"+response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(jsObjRequest);
}