I'm trying to use volley to make a request to this api (specifically the /BusinessTypes/basic endpoint) in order to get a list of types of catering businesses in the UK, but I keep getting an error.
Initially, I tried to retrieve the data during the onCreate method which is what I thought might have been the problem (however, ideally this is what I want to be able to do). After creating a test button on a blank activity and hooking that up to the code that makes the request, I still have the same problem.
I'm targeting API 21 (Not my choice & can't be changed).
This is the code corresponding to the plain activity with a single button that has id "but".
public class BasicActivity extends AppCompatActivity {
final String FSA_EP_T = "http://api.ratings.food.gov.uk/BusinessTypes/basic";
final String FSA_EP_R = "http://api.ratings.food.gov.uk/Regions";
final String FSA_EP_A = "http://api.ratings.food.gov.uk/Authorities/basic";
Button b;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_advanced_search);
b = findViewById(R.id.but);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
doStuff();
}
});
}
private void doStuff() {
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
JsonArrayRequest typeRequest = new JsonArrayRequest(
Request.Method.GET,
FSA_EP_T,
null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.e("businessType", String.valueOf(response));
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VolleyErr", "I keep seeing this!!!");
}
}
) {
#Override
public Map<String,String> getHeaders() {
Map<String, String> params = new HashMap<String, String>();
//The api requires me to specify the api version
params.put("x-api-version","2");
params.put("accept", "application/json");
return params;
}
};
typeRequest.setRetryPolicy(new DefaultRetryPolicy(
10000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(typeRequest);
}
}
After some playing around I finally realised my problem.
The api endpoint I am using returns a json object which contains a json array, not just a single json array like I assumed it would.
I extracted the array I needed using
response.getJSONArray("businessType");
where response is now a JSONObject.
I assumed an error like this would have shown up automatically in my log but it didn't.
For anyone else having similar problems, I recommend adding
Log.e("VolleyError", error.getMessage());
to the onErrorResponse method.
Related
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.
I'm trying to get an identification cookie sent from a website, and for this i'm using Volley library.
First of all, yes i have searched this subject extensively for the past couple of days and using all the answers i managed to rack up this code:
public class Login extends AppCompatActivity {
StringRequest stringRequest = null;
RequestQueue queue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
queue = Volley.newRequestQueue(this);
Button b = (Button) findViewById(R.id.bauth);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String url = "http://daviddurand.info/D228/pizza/?action=login&user=david";
stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
CookieManager manager = new CookieManager();
CookieHandler.setDefault(manager);
try {
Log.d("URI 1", manager.getCookieStore().get(new URI("http://daviddurand.info/D228/pizza/?action=login&user=david")).toString());
} catch (URISyntaxException e) {
e.printStackTrace();
}
Log.d("URIS", manager.getCookieStore().getURIs().toString());
Log.d("COOKIE", manager.getCookieStore().getCookies().toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//error
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
});
}
}
Which does not return anything more than empty brackets, so i'm guessing something(s) wrong..
For starters am i heading the right way here? and what exactly do i need to add to make this work?
you dont need to put this:
CookieManager manager = new CookieManager();
CookieHandler.setDefault(manager);
in your response. but only once before you start making calls.
Using CookieHandler HttpURLConnection, which apparently is the http stack you use :), takes care of the cookies so you need to take care of that in Volley itself.
so you can do
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
just before queue = Volley.newRequestQueue(this);
Good day, everyone. Please, I really need an answer to this.
I am new to Android development. I am trying to develop an app meant for broadcast messaging. I have been able to create a database where registered users are stored in a table. However, I lack the idea of what to do next.
Most of the tutorials I have seen teach how to make use of users registered on the PARSE platform. But I wonder if I could be able to lift the users on MySQL database and integrate it with any chat client. Thanks.
Check out the Volley library, it's a library made by Google to make requests.
here you have some explications about Volley. You'll need to import volley library in your project.
you have to create the singleton class given by Google (Here called mySingleton) and to create a request class with code like this one :
public class MyRequest {
private Context context;
private RequestQueue queue;
public MyRequest(Context context, RequestQueue queue) {
this.context = context;
this.queue = queue;
}
public void getArticles(final GetArticlesCallback callback){
String url = "YourScriptUrl";
StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
callback.onSuccess("I will get this string in the activity");
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
callback.onError("erreur : " + error.toString());
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<>();
map.put("tag", "postArgument1");
map.put("tag2", "postArgument2");
return map;
}
};
queue.add(request);
}
public interface GetArticlesCallback{
void onSuccess(String success);
void onError(String error);
}
}
And you call this class in your activity :
//queue is a RequestQueue
//request is a Myrequest
queue = VolleySingleton.getInstance(this).getRequestQueue();
request = new MyRequest(this, queue);
request.getArticles(new MyRequest.GetArticlesCallback() {
#Override
public void onSuccess(String success) {
}
#Override
public void onError(String error, String id) {
}
});
I have recently started on Android development platform. I am using Android Studio, and using Volley library for network operation. I have implemented a backend for push notification for iOS and it is working very well, and now I am triggering this php via Volley network operation as follows.
For some reasons it calls that URL multiple times (5 or 6 times), how do I know? because iOS device receives multiple notifications. I am not sure why this happens and how I could solve it?
public void onClick(View v) {
if(v == buttonBuy) {
message = (EditText) findViewById(R.id.offerText);
buy();
}
}
private void buy()
{
StringRequest postRequest = new StringRequest(Request.Method.POST, Config.ASK_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
) {
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<>();
params.put("token",token);
params.put("pname",objee.optString("pname"));
params.put("toid",objee.optString("uid"));
params.put("pid",pid);
params.put("message",message.getText().toString().trim());
return params;
}
};
CustomVolleyRequest.getInstance(this).getRequestQueue().add(postRequest);
}
Try to add the following code:
int socketTimeout = 10000; //10 seconds - change to what you want
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
postRequest.setRetryPolicy(policy);
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).