Here's my layout code;
static String userLocation(String url) {
RequestQueue queue = Volley.newRequestQueue(context);
// String url = "http://www.jobdiagnosis.com/iphone/userlocation.php";
StringRequest dr = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
res=response;
//edit_location.setText(response);
// Toast.makeText(context, response, Toast.LENGTH_LONG).show();
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error.
Toast.makeText(getApplicationContext(), "error"+error, Toast.LENGTH_LONG).show();
Log.d("error", ""+error);
}
}
);
queue.add(dr);
return res;
}
When I toast the response on same method then response prints fine
and when I call method and print return statement then res prints null.
Any help is appreciated. Thank you in advance.
Please suggest me how we can share response within a one or more activity
And sorry for my bad English..
this is an asynchronous request, the volley processes the request in background thread and delivers the response in onResponse()
if you're looking for synchronous response try this
Try to declare res like global variable. Not return value. Because you didn't know, when request will finished. And use this global variable.
Related
I am working on an Android app.
This is one function inside a fragment:
private void guardar_paciente() {
String tag_string_req = "req_login";
StringRequest strReq = new StringRequest(Request.Method.POST,
URL_CHECK, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
String id_paciente = jObj.getString("id");
String id_nhc = jObj.getString("nhc");
if (!error) {
editor2.putString("id_paciente", id_paciente);
editor2.putString("nhc", id_nhc);
editor2.apply();
} else {
// Error in login. Get the error message
// String errorMsg = jObj.getString("error_msg");
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
// Toast.makeText(getActivity(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(),
error.getMessage(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting parameters to login url
Map<String, String> params = new HashMap<String, String>();
params.put("nombre_completo", nombre_completo);
params.put("apellidos", apellidos);
params.put("tel1", tel1);
params.put("tel2", tel2);
params.put("email", email);
params.put("profesion", profesion);
params.put("sexo", sexo);
params.put("fecha_nacimiento", fecha_nacimiento);
params.put("edad", edad);
params.put("peso", peso);
params.put("talla", talla);
params.put("IMC", IMC);
params.put("consentimiento", "1");
params.put("clinica_paciente", clinica_actual);
params.put("imagen_paciente", imagen_paciente);
params.put("firma_paciente", numero+".JPG");
params.put("DNI", DNI);
params.put("direccion", direccion);
params.put("raza", raza);
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
}
What I need is to execute another function, abrirPaciente(), just after guardar_paciente() has finished all its methods and it is safe to change the UI.
I have tried calling abrirPaciente() just after editor2.apply();, but the app crashes.
Making use of callbacks :
public class foo {
interface ExampleInterface {
void finishedServiceCallNoErrors();
void finishedServiceCallWithError(String error);
}
void guardar_paciente(ExampleInterface exampleInterface) {
...
#Override
public void onResponse(String response) {
....
//there was no error
exampleInterface.finishedServiceCallNoErrors();
//there was an error
exampleInterface.finishedServiceCallWithError("your error message here");
....
}
...
}
}
and an example of how you'd make use of this :
public class bar implements foo.ExampleInterface {
//simple example of how you'd use this
private void callingIt() {
new foo().guardar_paciente(this); //here, we can pass `this` because our class is implementing the interface
}
//these now get returned to the class making use of the service call, so you can easily handle things here, instead of worrying about the logic in your service call response
#Override
public void finishedServiceCallNoErrors() {
//TODO("Handle the response with no error");
//your call completed and everything was fine, now do something else
}
#Override
public void finishedServiceCallWithError(String error) {
// TODO("Handle the response with an error")
// there was an error, handle it here
}
}
I'm not sure if this callback pattern will be safe to use if it's being triggered from a background thread, so for that you'd need to switch threads inside the callbacks, so inside finishedServiceCallNoErrors and inside finishedServiceCallWithError you'd potentially need like a Runnable, so you can make use of the main thread, or inside the onResponse of the service call, before triggering the callbacks, you could also change there to the main thread. You can find help with something like that here
So I've run into a problem in my code, where I need to get a JSONString from my server with volley. And then I have to parse the String into a JSONObject and then continue doing stuff with that.
My problem here is, that Volley gives the response too late, meaning my string that I want to parse is always empty because its not initialised yet.
RequestFuture<String> future = RequestFuture.newFuture();
StringRequest stringRequest = new StringRequest(Request.Method.GET, searchURLBuilder, future, future);
// new Response.Listener<String>() {
// #Override
// public void onResponse(String response) {
// writeToSharedResponse(response_for_search, response);
// }
// },
// new Response.ErrorListener() {
// #Override
// public void onErrorResponse(VolleyError error) {
// Log.d("Error!!:" + error.getMessage(), "");
// }
// });
requestQueue.add(stringRequest);
String response = "";
try {
response = future.get(60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
String responseString = m.getString(response_for_search, new String());
pieceDTOList = getPiecesDTOFromJSON(responseString);
Here is a snippet of my code. As you can see I already tried to make a "future" call to block and wait for the answer, but it just times out every time. The commented out bit, is the part I actually wanted to use from the beginning, but that returns the response to late. Since its asynchronous and accesses the server w/e it wants.
writeToSharedResponse just writes the answer into a sharedPreferences variable.
private SharedPreferences m;
private SharedPreferences.Editor editor;
private RequestQueue requestQueue;
public DbParser(Context c) {
m = PreferenceManager.getDefaultSharedPreferences(c);
editor = m.edit();
requestQueue = Volley.newRequestQueue(c);
}
My Question here is: Is there an easy way I can "wait" for the answer from volley so I can continue to work with the response that I get?
Edit 1:
I now added an interface and changed the code around to this:
getString(new VolleyCallback() {
#Override
public void onSuccess(String result) {
getPiecesDTOFromJSON(result);
}
}, searchURLBuilder);
return globalPieceDTOList;
}
private void getString(final VolleyCallback callback, String searchUrl){
StringRequest stringRequest = new StringRequest(Request.Method.GET, searchUrl,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
callback.onSuccess(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error!!:" + error.getMessage(), "");
}
});
requestQueue.add(stringRequest);
}
Since I cant get the values out of my inner classes, I did a nasty hack and created a global list for my DTO's. The problem now is that "return globalPieceDTOList" is always Null. And again - I would need to "wait" for the Volley response.
Volley requests are async, so when you try to return a value, the request is likely not done yet. If you want to return values from a Volley request use callback interfaces.
Example
public void getString(final VolleyCallback callback) {
StringRequest strReq = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// do some things here
callback.onSuccess(<PASS STRING RESULT HERE>);
}
});
}
public interface VolleyCallback{
void onSuccess(String result);
}
Example usage:
public void onResume(){
super.onResume();
getString(new VolleyCallback(){
#Override
public void onSuccess(String result){
//do stuff here with the result from the volley request
}
});
}
I need to make a JSON Request and set UI depending on its response, so it would nice to make it in onCreate in the same thread.
Speaking about RequestFuture, I can't reliably use it for this, or I don't know how to do it.
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(URL, null, future, future);
requestQueue.add(request);
try {
JSONObject response = future.get();
count = response.getIn("int");
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}catch (JSONException e) {
Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_LONG).show();
}
I tried this, but its dont work.
If someone know pls show an example how to get data from JSONObject and dont do nothing befor data is goten and than use that values to set some Views.
as there is getActivity() in your code, i bet you are in a fragment.
to do something on UI thread you could call something like this
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
// your UI-related code goes here
}
});
Using Volley you have listeners of response when succeed and an error listener when server has a respone with error code (500, 401).
So you can create a JSONObjectRequest like the following code lines:
JSONObjectRequest jsObjRequest = new JsonArrayRequest
(REQUEST_URL, new Response.Listener<JSONObjectRequest>() {
#Override
public void onResponse(JSONObjectRequest response) {
// this code will be executed when response comes and you can set your views, the way is depending where you are (fragment, activity, etc), you can do runOnUiThread
Log.d("Hello", "You can do whatever you want wen data is goten");
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error","You can show an error dialog here ");
}
});
You have to add the above object created to the HTTQueue and it will be executed at its time. Hope it helped !
if you are using volley then you can use the listeners. You can also refer this https://developer.android.com/training/volley/simple.html . In onResponse or onError you can do the UI changes that you want.
JsonArrayRequest request = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
});
I'm using google volley for networking in android. I will make a http GET request and need to return a response header value. I found some answers on stack overflow to access the header fields, but don't know how to return it to my calling spot.
Please have a look at my code, I put four numbers in it to explain my problem.
At (1) I can print out the value which I need. Than I've tried to save it in a class attribute (2) and there is no error in the IDE. If I want to return it from there (3), I got a NullPointerException at (4). Maybe its a read before write problem there.
So how can I get the value from (1) to (4)? Thanks a lot!
public class Login {
String phpsessid = null;
public Login() {}
public String getSessionId(Context context) {
RequestQueue queue = Volley.newRequestQueue(context);
StringRequest sr = new StringRequest(Request.Method.GET, "any url",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
System.out.println(response.headers.get("Set-Cookie")); (1)
phpsessid = response.headers.get("Set-Cookie"); (2)
return super.parseNetworkResponse(response);
}
};
queue.add(sr);
return phpsessid; (3)
}
}
in main:
Login login = new Login();
String result = login.getSessionId(this.getContext);
System.out.println(result); (4)
When you add a request to the queue, that request is executed asynchronously. This means it is not executed in the same order as you're reading it - it happens on another thread, and will return eventually when it's done.
protected Response<String> parseNetworkResponse(NetworkResponse response) {
System.out.println(response.headers.get("Set-Cookie")); (1)
phpsessid = response.headers.get("Set-Cookie"); (2)
return super.parseNetworkResponse(response);
}
This returns the body of the response - from what I'm reading in your code, it looks like you want to return the value of the "Set-Cookie" header. You can do this like this:
protected Response<String> parseNetworkResponse(NetworkResponse networkResponse) {
String sessionId = response.headers.get("Set-Cookie");
com.android.volley.Response<String> result = com.android.volley.Response.success(sessionId,
HttpHeaderParser.parseCacheHeaders(networkResponse));
return result;
}
This will return the value of the "Set-Cookie" header to your onResponse method:
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println(response);
}
}
A better idea may be to pass a success/failure listener in when making your getSessionId call. In this way, you can then easily get access to the result in the calling class:
public void getSessionId(Context context, final Response.Listener<String> successListener, Response.ErrorListener failureListener) {
RequestQueue queue = Volley.newRequestQueue(context); // This should be a singleton!
StringRequest sr = new StringRequest(Request.Method.GET, "any url",
successListener,
failureListener) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse networkResponse) {
String sessionId = response.headers.get("Set-Cookie");
com.android.volley.Response<String> result = com.android.volley.Response.success(sessionId,
HttpHeaderParser.parseCacheHeaders(networkResponse));
return result;
}
};
queue.add(sr);
}
Edit:
Now, you can call this as follows:
Login login = new Login();
login.getSessionId(this, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// You can access member variables from here.
// This will only get called after the network activity has happened!
phpsessid = response;
// All the work you need to do after your session ID has updated, you can put into a method and call it from here
// In your original example, this would be (4)
onSessionIdUpdated();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// We'll just ignore these for now - you should handle errors though!
}
});
// Anything you put here will happen immediately after the getSessionId call above, and notably *before* onResponse or onErrorResponse is called (ignoring potential race conditions here for now).
I want to pass a response outside of my classes (many classes)
public static void userLocation()
{
RequestQueue queue = Volley.newRequestQueue(context);
String url = "http://www.jobdiagnosis.com/iphone/userlocation.php";
StringRequest dr = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
//Toast.makeText(context, ""+response, Toast.LENGTH_LONG).show();
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error.
// Toast.makeText(getApplicationContext(), "error"+error, Toast.LENGTH_LONG).show();
Log.d("error", ""+error);
}
}
);
queue.add(dr);
}
Please suggest how I can pass a response outside of the class
In volly its difficult to return response outside the class.because request on server run in background and if we return value followed by queue.add(url) then it will return null.So there is no solution till now.Thanks!!