Volley Request call URL multiple times - android

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);

Related

Android Volley duplicates request

Volley request is done inside a while. It duplicates for no reason ( seemingly ) For example when I suppose to make two requests, volley does it 4 times. Below is my code, some of you could hint the problem in my code ?
while(i<chnumTxt.length()){
final RequestQueue queue;
queue = Volley.newRequestQueue(this);
char letter=chnumTxt.charAt(i);
Log.i("check","counter="+i+" "+"digit="+letter);
String URL = "http://192.168.4.20:80/chnumber?key="+letter;
Log.i("web",URL);
StringRequest request = new StringRequest(Request.Method.GET, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//Log.i("html",response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(request);
new CountDownTimer(500, 500) {
public void onFinish() {
// When timer is finished
// Execute your code here
}
public void onTick(long millisUntilFinished) {
}
}.start();
i++;
}
Eventually i found the answer somewhere. Volley will retry links if the link seems slow. So after blocking it, got it right. It is like :
First declare a variable :
static final float DEFAULT_BACKOFF_MULT = 1f;
and after defining the request, do below code :
request.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

Why do I keep getting an error response from Volley (Android)?

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.

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.

ReST API security

I am creating an Android App that will communicate with ReST API . And i want to know how do I provide security to the APIs
Here is my sample API method
#GET
#Path("/count")
public String totalUserCount(){
return "100";
}
and here is my call to api from android
StringRequest stringRequesttoNearby = new StringRequest(
Request.Method.GET,
url,
new Response.Listener<String>() {
#Override
public void onResponse(String responseString) {
//response
}
},
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;
}
};
//add request to queue
Singleton.getInstance().getRequestQueue().add(stringRequesttoNearby);
So I want to know how I can add security to this API call
You could use Oauth1.0a, Oauth2 check out the link
Follow link Secure Api

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