Android Volley return value from response - android

How do I get the response out of onResponse so that I can return it? I have found this but I don't really understand how to implement it for me. How can I return value from function onResponse of Volley?
I hope there is an updated method or something easier that I might have missed
This is my code
public Boolean checkIfPersonExists(Context context, final Person aPerson){
StringRequest postRequest = new StringRequest(Request.Method.POST, USEREXISTS, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("RESPONSE",response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("email",aPerson.getEmail());
params.put("phone",aPerson.getPhone());
return params;
}
};
Volley.newRequestQueue(context).add(postRequest);
return null;
}

As it was mentioned, you need to implement interface and get a callback
Create a new interface like this
public interface GeneralCallbacks {
void VolleyResponse(String data);
}
Implement the interface on your activity class
public class YourActivity implements ScoreboardCallback
{
#Override
public void VolleyResponse(String data)
{
//do stuff with data
}
}
And finally changing your response function to something like this
#Override
public void onResponse(String response) {
((GeneralCallbacks)context).VolleyResponse(response); // This will make a callback to activity.
aPerson.SomeFunction(); // This will call person's function
Log.d("RESPONSE",response.toString());
}

Related

Returning values from Volley / AsyncTask to calling method [duplicate]

This question already has answers here:
Wait for result of Async Volley request and return it
(2 answers)
Closed 3 years ago.
So say I have a class for performing Api calls that extends the volley Request class:
public class ApiCall extends Request<JSONObject> {
private Listener<JSONObject> listener;
private Map<String, String> params;
public ApiCall(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) {
}
#Override
protected void deliverResponse(JSONObject response) {
listener.onResponse(response);
}
}
And then I'm using this inside Classes for implementations for different apis so
public class Website_A_Api {
public getJson_foo(){
addToRequestQueue(new ApiCall(Request.Method.GET, fullUri, header, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//Do stuff here
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Handle Errors
}
}));
}}
This works fine as long as I do everything I need in onResponse. Problem is i need to somehow return the JSONObject to wherever getJson_foo() was called. I tried using FutureRequests for synchronous calls but that won't run on the ui thread. How would I go about doing this / setting up another thread to run a synchronous call on?
try this
JSONArray array = new JSONArray();
JSONObject object = new JSONObject();
object.put("Key","value");
array.put(object);
addToRequestQueue(new ApiCall(Request.Method.GET, fullUri, array, new Response.Listener<JSONObject>(){
#Override
public void onResponse(JSONObject response) {
//Do stuff here
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Handle Errors
}
}));
}}

Handle callbacks in my library

I have written an android library that does network calls to various websites and returns the necessary content. I am using Volley library which has callbacks like onResponse and onFailure. Initially this library was an app and was later changed to an library.
When it was an app I could handle the callbacks easily. Whenever the callback happens I call the required functions from there but now when I import as the library and try to use it the control returns from the library as soon as I call it and the call back is not doing anything.
public void sendForVerification(final String Response, final String Secret, final String Name) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
flag = true;
},
new Response.ErrorListener() {
#Override
public void onErrorResponse (VolleyError error){
flag = false;
}
}}) {
#Override
protected Map<String, String> getParams () throws AuthFailureError {
HashMap<String, String> params = new HashMap<>();
params.put("secret", Secret);
params.put("response", Response);
return params;
}
};
requestQueue.add(stringRequest);
}
}
When this code was a part of the app instead of returning the flag value I would call an appropriate function to handle the result. Now whenever I call these functions the value of flag is returned before the callback is done and this is causing some problem.
My question is how can I warp this around a callback so that the app that uses this library will be notified when the network call is done?
You could add your own callback(s) for your library
interface YourCallback<T> {
onResponse(T value);
}
public void sendForVerification(final String Response,final String Secret,final String Name, YourCallback<Boolean> callback){
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
callback.onResponse(true);
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
callback.onResponse(false);
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String,String> params = new HashMap<>();
params.put("secret",Secret);
params.put("response",Response);
return params;
}
};
requestQueue.add(stringRequest);
}
boolean flag;
api.sendForVerification("", "", "", new YourCallback<Boolean>() {
#Override
public void onResponse(Boolean value) {
flag = value;
}
});
Volley is asynchronus, so any other upcoming process after you send the request will continue as normal without waiting for a response. That's why your flag value seems like it hasn't changed, because you probably try to access it while the request is still waiting for a response. That's the reason of callback implementations: you take certain actions as soon as you get a response, and you shouldn't try to handle values that will be returned from another method, because they will be returned before they change.

Volly: Implemetation of methods by following DRY principle

I need to call an api to get a json data using android volly. I have a method implemented inside class A to call the get request as shown
class A{
public static String getList(Context context,String url)
{
final String[] result = new String[1];
JsonArrayRequest req = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.e("response",response.toString());
result[0] =response.toString();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("responseerror",error.toString());
result[0] =error.toString();
}
});
MySingleton.getInstance(context).addToRequestQueue(req);
return result[0];
}
}
Inside class B i am accesing this method
class B {
String responce= A.getList(activity,url);
}
Here i can pass the context and url to get json data. But the problem is getList() method ruturs result even before it gets any response from the server. The app have more than one class which needs to call get request. If i will use this code snippet inside every such class then it will be against DRY principle. So what is the proper procudure to follow in this scenario?
Use an interface like below.
class A {
private final WeakReference<ResponseListener> responseListenerWeakRef;
public A(ResponseListener responseListener) {
responseListenerWeakRef = new WeakReference<ResponseListener>(responseListener);
}
public String getList(Context context, String url) {
JsonArrayRequest req = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.e("response",response.toString());
if (responseListener!=null && responseListener.get()!=null) {
responseListener.get().onResponse(response.toString());
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("responseerror",error.toString());
if (responseListener!=null && responseListener.get()!=null) {
responseListener.get().onResponse(error.toString());
}
}
}
);
MySingleton.getInstance(context).addToRequestQueue(req);
}
public interface ResponseListener {
void onResponse(String response);
}
}
class B implements A.ResponseListener {
private void makeApiCall() {
new A(this).getList(activity, url);
}
#Override
public void onResponse(String response) {
// Do something with the response.
}
}

Volley Request Callback passing the wrong callback response

I've added a callback on the volley request and, I have two request started from 2 different activity. When I perform the first request, then the second return the response of the first..
This is my request and callback:
public static void RequestJsonToServer(Context ctx, final JSONObject params, final VolleyCallback callback){
MySingleVolley.getInstance(ctx).
getRequestQueue();
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,ctx.getString(R.string.defaultServerRequestUrl),params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
callback.onSuccess(response);
}
},new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("REQUEST_JSON_TO_SERVER", "Error: " + error);
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
return headers;
}
};
MySingleVolley.getInstance(ctx).addToRequestQueue(jsObjRequest);
}
public interface VolleyCallback{
void onSuccess(JSONObject string);
}
And this is one of the two starting request:
Global.RequestJsonToServer(getActivity(), jsonObject, new Global.VolleyCallback() {
#Override
public void onSuccess(JSONObject result) {
Toast.makeText(getActivity(),result.toString(), Toast.LENGTH_LONG).show();
}
});
I hope someone can help me
Thanks
Edit:
I change it like this
Global.RequestJsonToServer(getApplicationContext(), jsonObject, new Global.VolleyCallback() {
#Override
public void onSuccess(JSONObject result) {
Toast.makeText(getApplicationContext(), result.toString(), Toast.LENGTH_LONG).show();
}
#Override
public void onSuccessCustom(JSONObject string) {
}
}, true);
And the other one with false.. But maybe is the wrong way to use it..I would like to have one single callback and reuse it, not switch between two callbacks
MY SOLUTION
I've found my own solution, the problem wasn't in the callback but was in the volley request. The response of each request was cached and i don't know why, it will be return the wrong always the wrong response.
I've just added this before adding request to queue:
jsObjRequest.setShouldCache(false);
This is happening because your callback method is common[onSuccess(...)]why don't you write 2 call backs and based on the condition use the required callback.
To implement it write 2 methods in your interface and pass some sort of flag to choose callback.
Change your interface to this.
public interface VolleyCallback{
void onSuccess(JSONObject string);
void customOnSuccess(JSONObject string);
}
And your method to this
public static void RequestJsonToServer(boolean flag,Context ctx, final JSONObject params, final VolleyCallback callback){
MySingleVolley.getInstance(ctx).
getRequestQueue();
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,ctx.getString(R.string.defaultServerRequestUrl),params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if(flag){
callback.onSuccess(response);
}else{
callback.CustomOnSuccess(response);
}
}
},new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("REQUEST_JSON_TO_SERVER", "Error: " + error);
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
return headers;
}
};
MySingleVolley.getInstance(ctx).addToRequestQueue(jsObjRequest);
}
Yes its reusable use onSucces where ever you have only one callback use both when you have more than one.

Execute a Volley request after another one is finished

I have two Volley requests. The first request authenticates the user; the second one gets data from the server.
If I send a GET request and the user is not authenticated, I want to fire the first request, authenticate the user and then keep executing the second one once the user is successfully authenticated.
So, the solution is pretty simple. :)
After I learned about callbacks and how them work, I figured out how to do that. So, I implemented a interface that declared the methods I wanted to invoke:
public interface AuthenticationCallback {
public void onLoginSuccess(String result);
public void onLoginError(String result);
}
public interface ResponseCallback {
public void onLoginSuccess(String result);
public void onAuthorizationError(String result);
}
My function:
public void getConversationMessages(final Context context, final String conversationID, final ResponseCallback responseCallback) {
final String url = GET_CONVERSATION_MESSAGES + conversationID;
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (responseCallback != null) {
responseCallback.onLoginSuccess(response);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (error.networkResponse != null && error.networkResponse.statusCode == HttpURLConnection.HTTP_UNAUTHORIZED){
if (responseCallback != null) {
responseCallback.onAuthorizationError(error.getMessage());
}
}
}
})
{
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Cookie", AppSingleton.getInstance(context).getCookie());
headers.put("Content-Type", "application/json");
return headers;
}
};
AppSingleton.getInstance(context).getRequestQueue().add(stringRequest);
}
}
My Activity:
ServerConnection.getInstance().getConversationMessages(getApplicationContext(), id, new ResponseCallback() {
#Override
public void onLoginSuccess(String result) {
}
#Override
public void onAuthorizationError(String result) {
ServerConnection.getInstance().loginFunction(getApplicationContext(), userID, new AuthenticationCallback() {
#Override
public void onLoginSuccess(String result) {
ServerConnection.getInstance().getConversationMessages(getApplicationContext(), conID, new ResponseCallback() {
#Override
public void onLoginSuccess(String result) {
}
#Override
public void onAuthorizationError(String result) {
}
});
}
#Override
public void onLoginError(String result) {
}
});
}
});
Basically, the code will try to send a GETrequest. If the user is not authenticated, then it will execute the code at onAuthorizationError(), that will authenticate the user. Once the user is successfully authenticate, it will send the GET request again.
I think nesting callbacks like this is not a good practice, but I'll fix it later and update my answer.
If someone have a better way to implement that, please, post another answer!
You can put one volley method inside another, as soon as the first request gets finished it sends the another request.By doing this the data will be sent to the database and the same modified data can be fetched again. The code is as shown below.
StringRequest stringRequest = new StringRequest(Request.Method.POST, "YOUR_FIRST_URL", new Response.Listener < String > () {
#Override
public void onResponse(String response) {
StringRequest stringRequests = new StringRequest(Request.Method.POST, "YOUR_SECOND_URL", new Response.Listener < String > () {
#Override
public void onResponse(String response) {
try {
JSONArray genreArry = new JSONArray(response);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map < String, String > getParams() {
Map < String, String > params = new HashMap < String, String > ();
return params;
}
};
int socketTimeouts = 30000;
RetryPolicy policys = new DefaultRetryPolicy(socketTimeouts, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
stringRequests.setRetryPolicy(policys);
RequestQueue requestQueues = Volley.newRequestQueue(context);
requestQueues.add(stringRequests);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map < String, String > getParams() {
Map < String, String > params = new HashMap < String, String > ();
return params;
}
};
int socketTimeout = 30000;
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
stringRequest.setRetryPolicy(policy);
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.add(stringRequest);

Categories

Resources