TimerTask executing on unequal time intervals - android

I've been working on looping AsyncTask on Android. I used an idea suggested by one of user and I came up with this:
public void loopAsyncTaskGetter(){
final Handler handler = new Handler();
final Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
new GetTasksAsync().execute(getIntent().getStringExtra(MainActivity.EXTRA_ID));
} catch (Exception e) {
}
}
});
}
};
timer.schedule(doAsynchronousTask, 500, 1000*30);
}
My AsyncTask extending class looks like that:
class GetTasksAsync extends AsyncTask<String, Void, Void>{
ProgressDialog dialog;
#Override
protected void onPreExecute(){
//dialog stuff
super.onPreExecute();
}
#Override
protected Void doInBackground(String... data) {
//this method below returns JSON String from my PHP file
String jsonData = Webserv.getTaskJson(data[0]);
try {
JSONArray jsonArray = new JSONArray(jsonData);
for(int i=0; i<jsonArray.length(); i++){
//some json parsing, doesn't matter
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void v){
dialog.dismiss();
myAdapter.notifyDataSetChanged();
super.onPostExecute(v);
}
I call loopAsyncTaskGetter() on my onCreate() method of Activity and I expect to have things done once for 30 seconds, and again. The strange thing for me is, that sometimes it works once for 30 seconds, and sometimes it gets done f.e. 3 times in 5 seconds, like much more often. Could anybody tell me why it works this way? Where did I make a mistake?
Kind regards!

You don't cancel your Timer when you're done with it. And because of that, you probably have multiple timers running in the background. Pass your Timer as a parameter to your asynctask and cancel it in onPostExecute.

Related

How to load new values of JSON after every 10 seconds

Hi people I am getting problem in getting my latest JSON value after every 10 seconds. I have developed this code and now I am stucked in this. When I run this code it shows the value after second and did not get updated the second time. I have implemented the handler but it is also not working here.
public class MainActivity extends AppCompatActivity {
TextView a,b,c,d,e,f,g,h;
String result = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
a=(TextView) findViewById(R.id.a);
b=(TextView) findViewById(R.id.b);
c=(TextView) findViewById(R.id.c);
DownloadTask task = new DownloadTask();
task.execute("https://api.thingspeak.com/channels/12345/feeds.json?results=1");
}
public class DownloadTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL(urls[0]);
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = urlConnection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final String result) {
super.onPostExecute(result);
new Handler().postDelayed(new Runnable() {
public void run() {
search(result);
}
}, 10000);
}
public void search(String result){
try {
JSONObject jsonObject = new JSONObject(result);
JSONArray weatherInfo = jsonObject.getJSONArray("feeds");
JSONObject legsobject = weatherInfo.getJSONObject(0);
a.setText(legsobject.getString("field1"));
b.setText(legsobject.getString("field2"));
c.setText(legsobject.getString("field3"));
}catch (JSONException e) {
e.printStackTrace();
}
}
}
}
I want to get my value refreshed after every 10 seconds and it is not doing it.
Can any one guide me that how can I make it possible.
Try this code ..
private final int INTERVAL_MILLI = 60000; // define your time..
Handler mHandler;
#Override
protected void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(SyncData);
}
Runnable SyncData = new Runnable() {
#Override
public void run() {
// call your code here..
Log.e(TAG, "SyncData1: " + new java.sql.Date(System.currentTimeMillis()).toString());
final String Token = AppSetting.getStringSharedPref(mContext, Constants.USER_KEY_TOKEN, "");
if (!TextUtils.isEmpty(Token) && !CommonUtils.isServiceRunning(mContext)) {
Log.e(TAG, "SyncData2: " + new java.sql.Date(System.currentTimeMillis()).toString());
startService(new Intent(mContext, SyncService.class));
}
callSyncData();
}
};
public void callSyncData()
{
mHandler.postDelayed(SyncData, INTERVAL_MILLI);
}
and callSyncData() method called in activity onCreate method and run method.
To begin with, I don't like the idea of hammering the server with a request every 10s even nothing changes really. If you can move to a solution with notification from the server it will be better.
If you still need to do that you can use three common solutions to fire a repeating task with a period:
1- Use Timer & TimerTask
For this solution you need to declare your timer task to run:
final TimerTask repeatedTask = new TimerTask() {
#Override
public void run() {
//you stuff here
}
};
Then you need to schedule your task using a timer like below:
final Timer timer = new Timer();
timer.scheduleAtFixedRate(repeatedTask,0, 10 * 1000);
==> Don't forget to call timer.cancel(); when your are done (or activity pause, stop, ...)
2- Use ScheduledThreadPoolExecutor
This is basically a replacing for Timer task starting android 5.0. The setup is more easy and straightforward like below:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
//you stuff here
}
}, 0, 10, TimeUnit.SECONDS);
==> don't forget to shutdown your executor when you are done by calling : executor.shutdown();
3- Use Handler
The tip here is to repost the runnable after downloading your json like mentionned in the previous answer.
You can use TimerTask and Timer. If you need to update UI components you should run it on UI thread.
final TimerTask yourRepeatedTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//your code here
}
});
}
};
And the Timer which schedules your task in a given interval. In your case, it is 10s. Make sure to give the interval in milliseconds.
final Timer timer = new Timer();
timer.scheduleAtFixedRate(yourRepeatedTask ,0, 10 * 1000);
At last call timer.cancel() to stop the timer.
#Override
protected void onPause() {
if (timer != null) {
timer.cancel();
}
super.onPause();
}

Android: ProgressDialog not progressing inside a Thread

I'm calling several AsyncTasks to do a job. In order to know when they are done. I have an object (synchronized) with a numerator that holds the number of current running AsyncTasks.
After deploying all of them I do the following:
final ProgressDialog pd = new ProgressDialog(this);
pd.setMessage(getString(R.string.please_wait));
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setCancelable(false);
pd.setProgress(0);
pd.setMax(Utils.getAsyncs());
pd.show();
new Thread(new Runnable() {
#Override
public void run() {
while (Utils.getAsyncs() > 0)
pd.setProgress(pd.getMax() - Utils.getAsyncs());
runOnUiThread(new Runnable() {
public void run() {
pd.dismiss();
}
});
}
}).start();
When the dialog shows, it starts progressing but at some point it gets stuck til the end of everything and then dismisses (as expected).
I tried to put
pd.setProgress(pd.getMax() - Utils.getAsyncs());
also inside a runOnUiThread but that made things worse and I'm sure I'm missing something else. hence my question. Thanks
edited by request:
public static int getAsyncs() {
return asyncs;
}
edit 2: I did the following based on a comment
while (Utils.getAsyncs() > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
runOnUiThread(new Runnable() {
public void run() {
pd.setProgress(pd.getMax() - Utils.getAsyncs());
}
});
}
and it seems to be better
In your class fields
private Handler progressHandler = new Handler();
private Runnable progressRunnable = new Runnable() {
#Override
public void run() {
progressDialog.setProgress(progressValue);
progressHandler.postDelayed(this, 1000);
}
};
When the time consuming thread is started
// Here start time consuming thread
// Here show the ProgressDialog
progressHandler.postDelayed(progressRunnable, 1000);
When the time consuming thread ends
progressHandler.removeCallbacks(progressRunnable);
/// Here dismiss the ProgressDialog.
ADDED:
Instead new Thread(new Runnable) that you probably use for your time consuming code I propose to do this:
To initialize the task :
MyTask task = new MyTask();
task.execute();
// Here show the PorgressDialog
progressHandler.postDelayed(progressRunnable, 1000);
Add this private class inside your main class:
private class MyTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
//Here do your time consuming work
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
// This will be called on the UI thread after doInBackground returns
progressHandler.removeCallbacks(progressRunnable);
progressDialog.dismiss();
}
}
do something lik this
new Thread(new Runnable() {
public void run() {
while (prStatus < 100) {
prStatus += 1;
handler.post(new Runnable() {
public void run() {
pb_2.setProgress(prStatus);
}
});
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(prStatus == 100)
prStatus = 0;
}
}
}).start();

Android - Moveing an Activity inside of background thread

Every time I`m trying to finish an activity inside of a timer method, the activity comes back alive over and over again.
I running this activity:
public class PlayerNoAdmin extends ActionBarActivity {
Timer myTimer; boolean isAdmin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player_no_admin);
Intent oldIntent = getIntent();
if (oldIntent != null && oldIntent.hasExtra("THE_LIST")){
songs = oldIntent.getParcelableArrayListExtra("THE_LIST");
id = oldIntent.getIntExtra("ID",0);
listId = oldIntent.getIntExtra("LIST_ID",0);
isAdmin = oldIntent.getBooleanExtra("IS_ADMIN",false);
}
//update the list every k seconds
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, k_time2Update);
}
private void TimerMethod() {
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//Here check for update in the list every 30 seconds and send the new location
String url = getRunUrl();
new TaskMusicPlay().execute(url);
}
};
private class TaskMusicPlay extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String jsonResult = null;
try {
String url = params[0];
TestMain client = new TestMain();
jsonResult = client.doGetRequest(url);
} catch (IOException e) {
e.printStackTrace();
}
return jsonResult;
}
#Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
checkIfNew(aVoid);
}
private void checkIfNew(String result) {
try {
JSONObject object = new JSONObject(result);
String temp = object.getJSONObject("info").getString("isAdmin");
isAdmin = (temp.equals("true"));
if (isAdmin) {
Intent intent = new Intent(getApplication(),YouTubePlayer.class);
intent.putExtra("THE_LIST", songs);
intent.putExtra("ID", id);
intent.putExtra("LIST_ID",listId);
intent.putExtra("IS_ADMIN",isAdmin);
startActivity(intent);
finish();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
At the end, I succeeded to move to the YouTubePlayer activity, but every few seconds the app returns to the code of this activity (and then executes again the startActivity call and goes back to YouTubePlayer) and that's going on and on.
Your Timer is periodically calling the player to start over and over again.
You must make a cancel() call to the Timer if it is no longer needed so you prevent it from holding a reference for your activity and thus preventing from being removed from the backstack and GC.
http://developer.android.com/reference/java/util/Timer.html
And your Timer is not running on the same thread as it's code because the timer thread iis another Thread and the Code in the Timer is running on UI. You can check it out by adding some logs in the Timer's run method outside of the runOnUIThread() and inside of it.

Android listview timer run in every second

I have a issue with using a timer on a listview.
In the list item I showed using sqlite values. There is a textview which showing time difference of last updated time of the data and current time. i have to show it in every one second. so the user can know how long he updated the record.
I tried this in several ways.
First way
I tried to add timer in adapter class. so for every item new timer is created. so application crashed because of many timers run simultaneously.
Second way
I tried using adapter.notifyDataSetChanged() way. Like as this.
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
if (adapterChatThread != null) {
adapter.notifyDataSetChanged();
}
timerHandler.postDelayed(this, 1000); // run every second
}
};
timerRunnable.run();
I move to another activity when click on list item and user can come back to this Activity.
so in Onresume I used
timerHandler.postDelayed(timerRunnable, 500);
and OnPause
timerHandler.removeCallbacks(timerRunnable);
Issue is data is not showing well. I mean in every second data difference is not one second. some time differnce is 2sec, 5 sec, .. etc.
means timer is not working as I expected.
Third way
I used a asynctask and call it in every second using a timer.
class ThreadTimer extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void result) {
if (adapter != null)
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
I called this as in here
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
new ThreadTimer().execute();
timerHandler.postDelayed(this, 1000); // run every second
}
};
timerRunnable.run();
previous issue triggered. (data not showing well)
Fourth way
Using AsyncTask as this
class ThreadTimer extends AsyncTask<Void, Void, Void> {
void Sleep(int ms) {
try {
Thread.sleep(ms);
} catch (Exception e) {
}
}
#Override
protected Void doInBackground(Void... params) {
while (threadRun) {
Sleep(1000);
return null;
}
return null;
}
#Override
protected void onPostExecute(Void result) {
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
}
I called this class in OnResume.
In on pause I set threadRun= false;
issue is same.
please help me.
My requirement is update list item in every second.
Thank you.
edit
here is my adapter class textview update code.
Date lastUpdatedTime;
final ChatThreadDAO ctd = new ChatThreadDAO();
long timeForNextResponse = ctd.getLastRespondedTime(vct.get(position).getThread_id());
try {
if (vct.get(position).getThread_read_status() == 1 && timeForNextResponse > 0) {
final long respTime = timeForNextResponse;
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
lastUpdatedTime = formatter.parse(vct.get(position).getLast_updated_time());
final long timeDiff = (new Date()).getTime() - lastUpdatedTime.getTime();
if (timeDiff <= respTime) {
timeForNextResponse = respTime - timeDiff;
ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), timeForNextResponse);
holder.tvChatTimer.setVisibility(View.VISIBLE);
holder.tvChatTimer.setText(timeForNextResponse / 1000 + "");
} else {
ctd.updateTimeRespondToLastMsg(vct.get(position).getThread_id(), 0);
}
} else {
holder.tvChatTimer.setVisibility(View.INVISIBLE);
}
} catch (ParseException e) {
e.printStackTrace();
}
here vct is
Vector vct;
I assign the values to vector in adapter class constructer.
Here is an example similar to your case.
private class connectionControl extends Thread {
boolean stop_ = false;
public void stop_() {
this.stop_ = true;
}
public void run() {
System.out.println("Thread started:" + getClass().getSimpleName());
while(!this.stop_) {
try {
Thread.sleep(1000);
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Calendar c = Calendar.getInstance();
int rightNow = c.get(Calendar.SECOND) + c.get(Calendar.MINUTE)*60;
if(rightNow - lastUpdatedTime > 10) {
wirelessIcon.setImageResource(R.drawable.wirelessred);
}
else if(rightNow - lastUpdatedTime > 5) {
wirelessIcon.setImageResource(R.drawable.wirelessyellow);
}
else {
wirelessIcon.setImageResource(R.drawable.wirelessgreen);
}
}
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Thread stoped:" + getClass().getSimpleName());
}
}
You set your lastUpdatedTime the same way you created rightNow whenever you call notifyDataSetChanged() method of your adapter.

Android Timed Async Task

Hi currently i have the following code which utilizes Asycn Task and Timer.
My async task is basically trying to send a HTTP GET method from a URL where the response from the server could varies depending on connection and load.
What i would like to do is to have a timed async task. Where, it will schedule an AsyncTask every X second BUT if there is currently an Async Task in progress i would have to kill it first. Then start a new one.
Here is the code that i have at the moment:
private static boolean running = false;
Timer myTimer;
protected void onCreate(Bundle savedInstanceState) {
/* REST OF CODE OMITTED */
MyTimerTask myTask = new MyTimerTask();
myTimer = new Timer();
myTimer.schedule(myTask, 0, 10000);
}
/* REST OF CODE OMITTED */
private class MyTimerTask extends TimerTask {
public void run() {
if(!running){
Log.i("TAG", "NEW TIMER STARTED.");
RetrieveChatMessage task = new RetrieveChatMessage();
task.execute();
running = true;
}else{
running = false;
}
}
}
private class RetrieveChatMessage extends AsyncTask<String, Void, ArrayList<Chat>> {
#Override
protected ArrayList<Chat> doInBackground(String... params) {
// TODO Auto-generated method stub
ArrayList<Chat> cList = null;
String jResult = null;
Log.i("TAG", "RETRIEVING CHAT MESSAGE");
try {
jResult = ((new HttpRetriever())).getChatList(mAccount.email, mAccount.passwd);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
if(jResult != null){
Log.i("TAG", "JSON DATA: " + jResult);
cList = (new ChatHandlers()).getChatList(jResult);
}else{
cList = null;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("TAG", "JSON Exception " + e.toString());
}
return cList;
}
#Override
protected void onPostExecute(final ArrayList<Chat> result) {
Log.i("TAG", "ON POST EXECUTE");
if(result != null){
// Do something here
}
}
}
To be honest the code above works with slight issues:
1. It seems to execute the Async randomly, instead of every 10 seconds.
2. When i go to another activity, somewhat it prevents other Async task from doing its job (Which is also trying to retrieve JSON response from server).
I am not too worried about the later problem (and that is not the question i am asking). I just would like to know how to have a proper timed Async Task. Can anyone point me to a direction.
Thank you.
EDIT #1:
after reading #thepoosh comment's i tried the following (i put it in onCreate):
scheduleTaskExecutor= Executors.newScheduledThreadPool(5);
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
// Parsing RSS feed:
// myFeedParser.doSomething();
Log.w("THUMBQOO", "NEW TASK STARTED");
retrieveChat();
}
}, 0, 15, TimeUnit.SECONDS);
Result: i have a consistent execution of Task. However, it seems that retrieveChat(); is never be called after the first execution.
Actually AsyncTask is not used for long operations .Check Here
You should use a Thread that uses a interface to notify UI or you can simply use a Handler which is the most Preffered way in android. Simply you can do a task repeatedly for every 10 seconds by
handler.postDelayed(new Runnable() {
#Override
public void run() {
// do work
handler.postDelayed(10000);
}
}, 10000);
Declare a Handler object to maintain future task executor...
private Handler mTimerHandler = new Handler();
Write a thread which will execute your future task...
private Runnable mTimerExecutor = new Runnable() {
#Override
public void run() {
//write your code what you want to do after the specified time elapsed
if(!running){
RetrieveChatMessage task = new RetrieveChatMessage();
task.execute();
running = true;
}else{
running = false;
}
}
};
Call your future tast executor with time using hanlder...
mTimerHandler.postDelayed(mTimerExecutor, 10000);
You can cancle your future task executor any time by this...
mTimerHandler.removeCallbacks(mTimerExecutor);
I am not sure if this is a very good way of accomplishing this (my answer here below) :
Use a Handler, create a HandlerThread and keep posting messages to this handler.
For the handlers "handleMessage" method, you can do your task and again send a message back to the MessageQueue.
HandlerThread thread = new HandlerThread(<name>);
thread.start();
Looper looper = thread.getLooper();
CustomHandler handler = new CustomHandler(looper);
// The CustomHandler class
class CustomHandler extends Handler {
public CustomHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
//Do your operation here
handler.sendEmptyMessageDelayed(msg, <delayTime>);
}
}

Categories

Resources