How to change Volley request rate - android

I'm making multiple requests to Amazon Web Services. I'm getting the 503 error because I'm making too many request too quickly. I want to know how to set the time-out between different requests, not the same ones. I am not looking to set the retry policy. I am also not looking to time-trigger individual requests. I want to time the interval between requests. The reason is that I am looping so quickly and making so many requests, that timing-triggering them is equivalent to submitting them all that the same time. The whole point is to space the requests out evenly.

Since you don't show how you made multiple requests, so I suggest you refer to the following sample, then try applying to your code. Hope it helps!
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RequestQueue queue = Volley.newRequestQueue(this);
final String url = "http://google.com";
final Handler handler = new Handler();
for (int i = 0; i <= 5; i++) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i("onResponse", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("onErrorResponse", error.toString());
}
});
queue.add(request);
}
}, 2000); // 2000 miliseconds
}
}

assuming you have Request object , before adding the request to the queue you can do this
request.setRetryPolicy(new DefaultRetryPolicy(5000, 5, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
the 5000 indicates the time between each request in ms
the 5 is the number of times you want to send the request before it gives you timeout
for the sake of someone seeing this, this is how to use timers to manually seclude a task
Timer timer = new Timer();
final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
// Update UI here if u need
}
};
TimerTask task = new TimerTask () {
#Override
public void run () {
//send requests according to your logic here
}
};
timer.schedule(task, 0, 60000); // 60000 = 1 min

Was struggling with this too, til I got some help from another developer. Try something like this:
public class HTTP {
String getUrl;
Context context;
YTVisualizer ytv;
int numberOfCurrentRequests = 0;
public HTTP(Context context, YTVisualizer ytv){
this.context = context;
this.ytv = ytv;
}
public void get(final String url) {
numberOfCurrentRequests++;
new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(250 * numberOfCurrentRequests);
} catch(InterruptedException e) {
e.printStackTrace();
}
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
String[] parts = url.split("=");
final String key = parts[1];
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
//runs in thread main
public void onResponse(String response) {
Log.i("Response", response);
String title = new String();
try {
JSONObject obj = new JSONObject(response);
Iterator<String> str = obj.keys();
String key = str.next();
title = obj.getString(key);
} catch (JSONException e) {
e.printStackTrace();
}
ytv.SetVideosFromHTTPClass(key, title, response);
numberOfCurrentRequests--;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "Error: are you connected to the internet?", Toast.LENGTH_SHORT).show();
numberOfCurrentRequests--;
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
}).start();
}
}
It pauses inbetween proportional to the amount of current requests. The 1st one sleeps .25 s, the 2nd one .5s, the third one .75s, and so on. Theyre all scheduled in order.

I know this is an old question, but here is a solution written in Kotlin:
Inside your class with the RequestQueue, you can add
val throttleTimeout : Long = 100L
private val throttleQueue : ArrayBlockingQueue<Request<*>> = ArrayBlockingQueue(100);
private val throttleThread = Thread {
while(true){
val rqst = throttleQueue.take()
requestQueue?.add(rqst)
Thread.sleep(throttleTimeout)
}
}
fun <T> addToThrottledRequestQueue(request: Request<T>, tag: String){
request.tag = if (TextUtils.isEmpty(tag)) TAG else tag
throttleQueue.put(request)
}
And just make sure to start the thread in your class initialization. You can also mix this with a function to create non-throttled request and mix them together.
fun <T> addToRequestQueue(request: Request<T>, tag: String) {
request.tag = if (TextUtils.isEmpty(tag)) TAG else tag
requestQueue?.add(request)
}
The addToThrottledRequestQueue function will make sure those requests are throttled while other requests can flow freely.

Related

How to make multiple volley request?

I am working on chatbot which uses API to get data but when i make request in start it is working good but if i want to make another request , the result is still the old response from old request, which i have to send request again to get new result. Is there any solution ????
i tried wait() in function that have volley requests but it does not work
public String getResult(String team1,String team2,String code,Context context)
{
this.context=context;
//"https://apifootball.com/api/?action=get_H2H&firstTeam=Arsenal&secondTeam=Chelsea&APIkey=7"
String URL="https://apifootball.com/api/?action=get_H2H&firstTeam="+team1+"&secondTeam="+team2+"&APIkey=7";
//"https://apifootball.com/api/?action=get_countries&APIkey=7";
RequestQueue rq= Volley.newRequestQueue(context);
JsonObjectRequest objreq= new JsonObjectRequest(
Request.Method.GET,
URL,
null,
new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response) {
String Scores="";
// Log.e("result:",response.get(0).toString());
JSONObject obj;
// obj=response.getJSONObject("firstTeam_VS_secondTeam");
try {
JSONArray obj2 =response.getJSONArray("firstTeam_VS_secondTeam");
Log.e("obj", obj2.getJSONObject(0).getString("match_hometeam_score"));
Scores=Scores+ obj2.getJSONObject(0).getString("match_hometeam_score")+"\n"+obj2.getJSONObject(0).getString("match_awayteam_score")+"\n"+obj2.getJSONObject(0).getString("match_date");
} catch (JSONException e) {
}
String []arr = Scores.split("\n");
model = new ChatModel("First team:"+arr[0]+"\nSecond team:"+arr[1]+"\n"+"Date:"+arr[2], false);
list_chat.add(model);
//share(Scores);
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
Log.e("rest response",error.toString());
}
}
);
rq.add(objreq);
SharedPreferences m= PreferenceManager.getDefaultSharedPreferences(context);
final String resp=m.getString("Response","");
return resp;
}
main activity
if(result.equals("error")==true) {
APIAdapter ap = new APIAdapter();
head2Head = ap.getResult("Bristol City", "Reading", "kjkn", getApplicationContext());
finres = head2Head;
Log.e("headto",head2Head);
arr = head2Head.split("\n");
//send(arr[2],false);
// model = new ChatModel("First team:"+arr[0]+"\nSecond team:"+arr[1]+"\n"+"Date:"+arr[2], false); // user send message
/*
Team t1=new Team(3,"Bristol City");
Team t2=new Team(0,"Reading");
Long tid1=x.insertTeam(t1);
Long tid2=x.insertTeam(t2);
Match m=new Match(0,Integer.parseInt(String.valueOf(tid1)),Integer.parseInt(String.valueOf(tid2)),arr[2]);
Long mid=x.insertMatch(m);
Log.e("mid",String.valueOf(mid));
Result resul=new Result(0,Integer.parseInt(String.valueOf(mid)),x.getTeam(tid1).getTeamId(),x.getTeam(tid2).getTeamId(),Integer.parseInt(arr[0]),Integer.parseInt(arr[1]));
x.insertResult(resul);
*/}
send("First team:"+arr[0]+"\nSecond team:"+arr[1]+"\n"+"Date:"+arr[2], false);
}
send()
void send(String text,boolean sender)
{
ChatModel model = new ChatModel(text,sender); // user send message
list_chat.add(model);
CustomAdapter adapter = new CustomAdapter(list_chat,getApplicationContext());
listView.setAdapter(adapter);
//remove user message
editText.setText("");
}
I am not sure if i understand what your problem is but i will do my best to help.
Define RequestQueue outside of the function(onCreate() can be a good place), this way you don't init it every time you make a request and it can actually work as a Queue for requests.
There might be a problem with the way you handle list_chat, please post the code that you use to display it.

Arraylist that sometimes contain data, and sometimes not

A newbie for here.
I'm working in an app with Android and a strange thing happens to me with a While loop. I make a series of requests to the database with volley library and it returns the data well. No problem.
The problem, i think, is in the last function DameColorPlato(), because sometimes the code accesses the while loop and it passes through it well, but sometimes it does not, and it returns the default value of the CC variable (#000000) and it does not show me well the colors of the text.
This is my code (In summary):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
Bundle datos = getIntent().getExtras();
id_usuario = datos.getString("id_usuario");
idCentro = datos.getString("id_centro");
fecha_actual = datos.getString("fechaActual");
fecha_actual_SQL = datos.getString("fechaActualSQL");
plato1 = (TextView)findViewById(R.id.textView4);
plato2 = (TextView)findViewById(R.id.textView3);
ObtPlatos_volley(idCentro, fecha_actual_SQL);
ObtColores_volley();
public void ObtPlatos_volley(final String id_centro, final String fecha_actual_SQL){
String url = "http://neton.es/WS_neton/menu_dia.php?id_centro="+id_centro+"&fecha_actual_SQL="+fecha_actual_SQL;
StringRequest eventfulRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
for (int i=0; i<jsonArray.length(); i++) {
platouno = jsonArray.getJSONObject(i).getString("plato1");
platodos = jsonArray.getJSONObject(i).getString("plato2");
platounoColor = jsonArray.getJSONObject(i).getInt("tipo1");
platodosColor = jsonArray.getJSONObject(i).getInt("tipo2");
}
plato1.setText(platouno);
String co1 = DameColorPlato(CodTipoPlato, ColorLetra, platounoColor);
plato1.setTextColor(Color.parseColor(co1));
plato2.setText(platodos);
String co2 = DameColorPlato(CodTipoPlato, ColorLetra, platodosColor);
plato2.setTextColor(Color.parseColor(co2));
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error: ", error.toString());
}
});
VolleySingleton.getInstance(this)
.addToRequestQueue(eventfulRequest);
}
public void ObtColores_volley(){
String url = "http://neton.es/WS_neton/color_platos.php";
StringRequest eventfulRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
int cod_color_letra;
String color_letra;
JSONArray jsonArray = new JSONArray(response);
for (int i=0; i<jsonArray.length(); i++){
cod_color_letra = jsonArray.getJSONObject(i).getInt("cod_tipoplato");
color_letra = jsonArray.getJSONObject(i).getString("color");
CodTipoPlato.add(cod_color_letra);
ColorLetra.add(color_letra);
}
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error: ", error.toString());
}
});
VolleySingleton.getInstance(this)
.addToRequestQueue(eventfulRequest);
}
public String DameColorPlato(ArrayList<Integer> CodColorL, ArrayList<String> ColorL, int tipoplato){
String CC="#000000";
int i=0;
boolean encontrado=false;
while (i < CodColorL.size() && !encontrado) {
if (tipoplato == CodColorL.get(i)) {
CC = ColorL.get(i);
encontrado = true;
}else {
i++;
}
}
return CC;
}
}
With a Toast I have found that ArrayList CodColorL and ArrayList ColorL variables sometimes come with values, and sometimes they come empty. But i cannot found the error.
Thanks in advance!
(sorry for my bad English)
As I explained out in the comments, for anyone else looking at this question, the reason why OP was seeing the issue of unreliable data is because they are making two Volley requests and expecting one to finish before implicitly.
By default, Volley requests are run in a queue but are Asynchronous which means that the requests won't necessarily finish in the order that they were started in the queue. Since OP's one request is dependent on the data from the other the correct way to do this is by synchronously running the requests. This can be done in a few ways such as using a callback from the first request or through starting the second request in the onResponse block of the first one.
One more way to achieve the same is to create your own architecture of running requests where you have a way to run all the requests on a single thread but that is over optimizing for this particular case.

Volley Request becomes too slow when phone goes to sleep and come back again to Application

I am facing the unidentified issue from several days that volley request becomes too slow when phone goes to sleep mode for some time and then return back to the app,i tried so many Retrypolicies given by volley, but none of them working correctly.below is my example code requesting volley to get data.
JsonObjectRequest movieReq = new JsonObjectRequest(
"MyURL" + session.getBusinessUserRegisterID(),
null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String Connectionscount = response.getString("Connections");
String Expiredcountval = response.getString("Expired");
String Livecountval = response.getString("Live");
String NewCustomerscount = response.getString("NewCustomers");
String NewNotificationscount = response.getString("NewNotifications");
String SmsBalancecount = response.getString("SmsBalance");
String TotalCustomercount = response.getString("TotalCustomer");
Newnotificationscount.setText(NewNotificationscount);
Livecount.setText(Livecountval);
Expiredcount.setText(Expiredcountval);
Totalcustcount.setText(TotalCustomercount);
Newcustcount.setText(NewCustomerscount);
Myconnectionscount.setText(Connectionscount);
Smscount.setText(SmsBalancecount);
ringProgressDialog.dismiss();
mSwipeRefreshLayout.setRefreshing(false);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
movieReq.setRetryPolicy(
new DefaultRetryPolicy(
10000,0,1f
)
);
AppController.getInstance().addToRequestQueue(movieReq);
First case placing second parameter of DefaultRetryPolicy greater than 0,it takes too long to give response
movieReq.setRetryPolicy(
new DefaultRetryPolicy(
10000,1,1f
)
);
Second case placing Second parameter as 0 so i can be given error if volley doesn't responds for 10 seconds(I am showing alert to retry).
movieReq.setRetryPolicy(
new DefaultRetryPolicy(
10000,0,1f
)
);
Try setting Priority high as :
#Override
public Priority getPriority() {
return Priority.HIGH;
}

How to update ui if there is new data in response using volley?

I have a code which gets data from the web service and displays the response in a textview. However, If the data changes in the webservice, I want to be able to update my textview with the new data and possibly play a notification sound indicating that there is a new data. I have tried doing polling, in which I will send request to the web service for data every x second. The problem though, is that after a few minutes, my app crashes because of out of memory. Also, regarding the notification sound, my idea was that, if the textview value changes, only then will the sound play or an alert dialog will appear. What happened in my case was that, since I am polling every x second, then the textview refreshes every x second as well, resulting in the alert dialog box appearing every x second. What is the best method for me to use to achieve what I want?
ParseJson
public class ParseJson {
public static String[] playing;
public static final String JSON_ARRAY = "result";
public static final String RESULT_ID = "playing";
private JSONArray users = null;
private String json;
public ParseJson(String json){
this.json = json;
}
public void parseJSON(){
JSONObject jsonObject=null;
try {
jsonObject = new JSONObject(json);
users = jsonObject.getJSONArray(JSON_ARRAY);
playing = new String[users.length()];
for(int i=0;i<users.length();i++){
JSONObject jo = users.getJSONObject(i);
playing[i] = jo.getString(RESULT_ID);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
public TextView text;
MediaPlayer mp;
public static final String JSON_URL = "http://172.16.51.118/androidphp/data.php";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
text.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
new AlertDialog.Builder(MainActivity.this)
.setTitle("Response")
.setMessage("text has changed")
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
}
})
.setIcon(android.R.drawable.btn_star)
.show();
}
#Override
public void afterTextChanged(Editable s) {
}
});
handleMe();
}
public void handleMe() {
Timer timer = new Timer();
final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
// do something on UI
}
};
TimerTask task = new TimerTask () {
#Override
public void run () {
//send volley request here
//RequestData requestData = new RequestData(MainActivity.this);
//requestData.sendRequest(text);
//text.setText(ParseJson.playing[0]);
/*(RequestData requestData = new RequestData(MainActivity.this);
requestData.sendRequest();*/
sendRequest();
}
};
timer.schedule(task, 0, 10000); // 60000 is time in ms
}
public void sendRequest(){
//While the app fetched data we are displaying a progress dialog
//final ProgressDialog loading = ProgressDialog.show(this,"Fetching Data","Please wait...",false,false);
StringRequest stringRequest = new StringRequest(JSON_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//text.setText(response);
//loading.dismiss();
showJSON(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_LONG).show();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
requestQueue.add(stringRequest);
}
private void showJSON(String json){
ParseJson pj = new ParseJson(json);
pj.parseJSON();
text.setText(ParseJson.playing[0]);
}
}
You shouldn't requesting your server every X sec. You can use GCM Api from Google to send packets directly on the device. Take a look at the doc.
Otherwise, you can do a singleton, like here, to avoid reallocating a queue each request.

JSON Download # onCreateView leaves recyclerView empty

if (isConnected()) {
Event eInstance = new Event();
theEvents = eInstance.downloadEvents(eventsNightlife, getActivity());
rAdapter = new RecyclerAdapter(theEvents);
recyclerView.setAdapter(rAdapter);
progrsBar.setVisibility(View.GONE);
....
This is part of the code that runs at "onCreateView". The method downloadEvents uses Volley to download JSON data, extract it and return a list of items (theEvents). Now when my app starts, the recycler view is empty. If I go to my home screen out of the app and then run my app again, this time the data sometimes gets downloaded.
I debugged step by step, and at first launch (i mean when the app is not just resuming), theEvents is empty, so the download didn't return or manage to return anything...
Suggestions on how to execute things before the UI has been shown to the user or what actually needs to be done to approach this task better?
Also, I use a swipeRefreshLayout and at its onRefresh method I do:
public void onRefresh() {
Event eInstance = new Event();
theEvents = eInstance.downloadEvents(eventsNightlife, getActivity());
rAdapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
but it doesn't work. I also tried to
rAdapter = new RecyclerAdapter(theEvents);
rAdapter.notifyDataSetChanged();
recyclerView.swapAdapter(rAdapter, false);
still not working.
EDIT: My downloadEvents method implementing Volley:
public List<Event> downloadEvents(String urlService, Context context) {
eventsList = new ArrayList<>();
RequestQueue requestQueue = Volley.newRequestQueue(context);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest
(Request.Method.GET, urlService, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
String durationStr = null;
for (int i = 0; i < response.length(); i++) {
JSONObject eventJson = response.getJSONObject(i);
String title = eventJson.getString("EventTitle");
String body = eventJson.getString("EventBody");
String date = eventJson.getString("EventDate");
String time = eventJson.getString("EventTime");
int duration = Integer.parseInt(eventJson.getString("EventDuration"));
if (duration > 60) {
durationStr = "Duration: " + duration / 60 + " h";
} else if (duration < 60) {
durationStr = "Duration: " + duration + " m";
}
String place = eventJson.getString("EventPlace");
String organ = eventJson.getString("Organization");
Event event = new Event(title, body, date, time, durationStr, place, organ);
eventsList.add(event);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY ERROR", "" + error);
}
}
);
requestQueue.add(jsonArrayRequest);
return eventsList;
}
You can use EventBus for your purpose that is a simple and truth way.
Here, i write an example for how to use EventBus with volley.
Consider that i want to download some data.
This is the class that my download methods is inside it (you can add more methods to it in the future):
Im used volley to download my data:
// Download methods is inside volley
public class MyDownloader{
public static void downloadData(){
DownloadDataEvent dlDataEvent=new DownloadDataEvent();
List<String> myResult=new ArrayList<>();
...
#Override
public void onResponse(JSONArray response) {
super.onResponse(response);
if(respone!=null){
// Do what i want with my received data
dlDataEvent.setData(response);
}
// Post my event by EventBus
EventBus.getDefault().post(dlDataEvent);
...
}
}
}
This is my event:
public class DownloadDataEvent{
private JSONArray mData;
public void setData(JSONArray data){
mData=data;
}
public JSONArray setData(){
return mData;
}
}
Now i want to use my downloadData() method inside my MainActivity:
(I called my downloadData method inside onCreate.)
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
// I have to register this class for EventBus subscriber:
if(!EventBus.getDefault().isRegister(this)){
EventBus.getDefault().registerSticky(this);
}
// Call my downloadData method
if(isConnected()){
MyDownloader.downloadData();
}
}
// And for receive the data through EventBus, i have to create a
// method (subscriber) in this template:
public void onEventMainThread(DownloadDataEvent downloadDataEvent){
JSONArray result=downloadDataEvent.getData();
// Do what i want with my received data
}
}
you can create more than one subscriber every where you want to use received data.
I passed JSONArray to my DownloadDataEvent that it is not good. you can deserialize your received data and pass it to your DownloadDataEvent.
I used Volley to download data
Maybe my descriptions were confusing, but EventBus is a well-known library and is very easy to use.

Categories

Resources