Android - Run a thread repeatingly within a timer - android

First of all, I could not even chose the method to use, i'm reading for hours now and someone says use 'Handlers', someone says use 'Timer'. Here's what I try to achieve:
At preferences, theres a setting(checkbox) which to enable / disable the repeating job. As that checkbox is checked, the timer should start to work and the thread should be executed every x seconds. As checkbox is unchecked, timer should stop.
Here's my code:
Checking whether if checkbox is checked or not, if checked 'refreshAllServers' void will be executed which does the job with timer.
boolean CheckboxPreference = prefs.getBoolean("checkboxPref", true);
if(CheckboxPreference == true) {
Main main = new Main();
main.refreshAllServers("start");
} else {
Main main = new Main();
main.refreshAllServers("stop");
}
The refreshAllServers void that does the timer job:
public void refreshAllServers(String start) {
if(start == "start") {
// Start the timer which will repeatingly execute the thread
} else {
// stop the timer
}
And here's how I execute my thread: (Works well without timer)
Thread myThread = new MyThread(-5);
myThread.start();
What I tried?
I tried any example I could see from Google (handlers, timer) none of them worked, I managed to start the timer once but stoping it did not work.
The simpliest & understandable code I saw in my research was this:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
}
},
5000
);

Just simply use below snippet
private final Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
//
// Do the stuff
//
handler.postDelayed(this, 1000);
}
};
runnable.run();
To stop it use
handler.removeCallbacks(runnable);
Should do the trick.

Use a CountDownTimer. The way it works is it will call a method on each tick of the timer, and another method when the timer ends. At which point you can restart if needed. Also I think you should probably be kicking off AsyncTask rather than threads. Please don't try to manage your own threads in Android. Try as below. Its runs like a clock.
CountDownTimer myCountdownTimer = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
// Kick off your AsyncTask here.
}
public void onFinish() {
mTextField.setText("done!");
// the 30 seconds is up now so do make any checks you need here.
}
}.start();

I would think to use AlarmManager http://developer.android.com/reference/android/app/AlarmManager.html
If checkbox is on call method where
AlarmManager alarmManager = (AlarmManager)SecureDocApplication.getContext()
.getSystemService(Context.ALARM_SERVICE);
PendingIntent myService = PendingIntent.getService(context, 0,
new Intent(context, MyService.class), 0);
long triggerAtTime = 1000;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 5000 /* 5 sec*/,
myService);
If checkbox is off cancel alarm manager
alarmManager.cancel(myService);

"[ScheduledThreadPoolExecutor] class is preferable to Timer when multiple worker threads are needed, or when the additional flexibility or capabilities of ThreadPoolExecutor (which this class extends) are required."
per...
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html
It's not much more than the handler, but has the option of running exactly every so often (vice a delay after each computation completion).
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
...
final int THREAD_POOL_SIZE = 10;
final int START_DELAY = 0;
final int TIME_PERIOD = 5;
final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
ScheduledThreadPoolExecutor pool;
Runnable myPeriodicThread = new Runnable() {
#Override
public void run() {
refreshAllServers();
}
};
public void startTimer(){
pool.scheduleAtFixedRate(myPeriodicThread,
START_DELAY,
TIME_PERIOD,
TIME_UNIT);
}
public void stopTimer(){
pool.shutdownNow();
}

Thanks to everyone, I fixed this issue with using Timer.
timer = new Timer();
timer.scheduleAtFixedRate(
new java.util.TimerTask() {
#Override
public void run() {
for (int i = 0; i < server_amount; i++) {
servers[i] = "Updating...";
handler.sendEmptyMessage(0);
new MyThread(i).start();
}
}
},
2000, 5000);

Related

Android Timer Schedule

Following is the code snippet which I am using in my project to schedule a task
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
#Override
public void run() {
//Do Something
}
}, interval, interval);
This works fine. I get event after mentioned interval. But this fails to send any event if date is set smaller than current from settings.
Does any one know why this behavior is happening?
Timer fails when you change the system clock because it's based on System.currentTimeMillis(), which is not monotonic.
Timer is not an Android class. It's a Java class that exists in the Android API to support existing non-Android libraries. It's almost always a bad idea to use a Timer in your new Android code. Use a Handler for timed events that occur within the lifetime of your app's activities or services. Handler is based on SystemClock.uptimeMillis(), which is monotonic. Use an Alarm for timed events that should occur even if your app is not running.
Use this code.. this will help you..
Timer t;
seconds = 10;
public void startTimer() {
t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (seconds == 0) {
t.cancel();
seconds = 10;
// DO SOMETHING HERE AFTER 10 SECONDS
Toast.makeText(this,"Time up",Toast.LENGTH_SHORT).show();
}
seconds -= 1;
}
});
}
}, 0, 1000);
}

How can I control a timer in android?

I want to make an application about mini game.
Detail : In 2 seconds you must to answer a question if you don't answer or the answer is wrong -> Game Over . But if your answer is true the Timer will reset become 0 and countdown again with diffirent question.
I have already seen many code about timer in website but I don't understand clearly about it :(
So I want to ask : How can i set up a timer run only 2 seconds and how can i reset it and continue with a new question ?
Please help me.
you can use CountDownTimer in android like this:
public class Myclass {
myTimer timer =new myTimer(2000,1000);
public void creatQuestion(){
timer.start();
//method you init question and show it to user
}
public void getUserAnswer(/*evry thing you expected*/)
{
//if answer is true call timer.start()
//else call timer.onFinish(); to run onfinish in timer
}
public class myTimer extends CountDownTimer {
public myTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
// you can update ui here
}
#Override
public void onFinish() {
this.cancel();
//fire game over event
}
}
}
i hope it make you satisfy
I've done something similar using Thread/Runnable.
Thread t = new Thread(new Runnable() {
public void run() {
final long startTime = getTime();
final long maxEndTime = startTime + 2000L;
try {
while (shouldContinueWaiting()) {
if (getTime() > maxEndTime) {
throw new TimeoutException();
}
sleep();
}
} catch (InterruptedException e) {
handleInterrupt();
} catch (TimeoutException e) {
handleTimeout();
}
}
boolean shouldContinueWaiting() {
// Has the user already answered?
}
void handleInterrupt() {
// The user has answered. Dispose of this thread.
}
void handleTimeout() {
// User didn't answer in time
}
void sleep() throws InterruptedException {
Thread.sleep(SLEEP_DURATION_IN_MILLIS);
}
void getTime() {
return System.currentTimeMillis();
}
then you can start/restart the thread by:
t = new Thread(same as above...);
t.start();
and stop by:
t.interrupt();
We want to use the Timer class.
private Timer timer;
When you're ready for the timer to start counting -- let's say it's after you press a certain button -- do this to start it:
timer = new Timer();
timer.scheduleAtFixedRate(incrementTime(), 0, 100);
The first line is us creating a new Timer. Pretty standard. The second line, however, is the one I wanted you to see.
incrementTime() is a method that is called at the end of every "tick" of the clock. This method can be called whatever you want, but it has to return an instance of TimerTask. You could even make an anonymous interface if you want, but I prefer moving it off into its own section of code.
The 0 is our starting location. We start counting from here. Simple.
The 100 is how large a "tick" of the clock is (in milliseconds). Here, it's every 100 milliseconds, or every 1/10 of a second. I used this value at the time of writing this code because I was making a stopwatch application and I wanted my clock to change every 0.1 seconds.
As for your project, I'd suggest making the timer's task be your question switch method. Make it happen every 2000 milliseconds, or 2 seconds.
You can use a Handler.
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
//this will happen after 2000 ms
}
}, 2000);
Maybe this can help you:
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
// FIRE GAME OVER
handler.postDelayed(this, 2000); // set time here to refresh textView
}
});
You can fire your game over after 2000 milliseconds.
If you get the question correct -> remove callback from handler and reset it when the next question starts.

How to run an async task for every x mins in android?

how to run the async task at specific time? (I want to run it every 2 mins)
I tried using post delayed but it's not working?
tvData.postDelayed(new Runnable(){
#Override
public void run() {
readWebpage();
}}, 100);
In the above code readwebpage is function which calls the async task for me..
Right now below is the method which I am using
public void onCreate(Bundle savedInstanceState) {
readwebapage();
}
public void readWebpage() {
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute("http://www.google.com");
}
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response1 = "";
response1=read();
//read is my another function which does the real work
response1=read();
super.onPostExecute(response1);
return response1;
}
protected void onPostExecute(String result) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
TextView tvData = (TextView) findViewById(R.id.TextView01);
tvData.setText(result);
DownloadWebPageTask task = new DownloadWebPageTask();
task.execute(new String[] { "http://www.google.com" });
}
}
This is what I my code is and it works perfectly fine but the big problem I drains my battery?
You can use handler if you want to initiate something every X seconds. Handler is good because you don't need extra thread to keep tracking when firing the event. Here is a short snippet:
private final static int INTERVAL = 1000 * 60 * 2; //2 minutes
Handler mHandler = new Handler();
Runnable mHandlerTask = new Runnable()
{
#Override
public void run() {
doSomething();
mHandler.postDelayed(mHandlerTask, INTERVAL);
}
};
void startRepeatingTask()
{
mHandlerTask.run();
}
void stopRepeatingTask()
{
mHandler.removeCallbacks(mHandlerTask);
}
Note that doSomething should not take long (something like update position of audio playback in UI). If it can potentially take some time (like downloading or uploading to the web), then you should use ScheduledExecutorService's scheduleWithFixedDelay function instead.
Use Handler and PostDelayed:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
readWebpage();
handler.postDelayed(this, 120000); //now is every 2 minutes
}
}, 120000); //Every 120000 ms (2 minutes)
you can use TimerTask instead of AsyncTask.
ex:
Timer myTimer = new Timer("MyTimer", true);
myTimer.scheduleAtFixedRate(new MyTask(), ASAP, TWO_MINUTES);
private class MyTask extends TimerTask {
public void run(){
readWebPage();
}
}
When phone goes to sleep mode, to save battery, and it is quite possible to happen within 2 mins interval, Handler.postDelayed() may miss scheduled time. For such activities you should use AlarmManager, get a lock with PowerManager to prevent going to sleep back while you're running the AsyncTask.
See my post with code sample here
Also you may want to read Scheduling Repeating Alarms
I suggest to go with Handler#postDelayed(Runnable). Keep in mind that this method will work only when your app is running (may be in background) but if user closes it manually or simply Android runs out of memory it'll stop working and won't be restarted again later - for that you need to use services.
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 2 * 60 * 1000); // every 2 minutes
/* your code here */
}
}, 2 * 60 * 1000); // first run after 2 minutes
This code will wait 2 minutes, execute your code, and then keep doing that every 2 minutes. But if you want it to run instantly for the first time - and then start the wait-do loop, instead use:
final Handler handler = new Handler();
/* your code here */
new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 2 * 60 * 1000); // every 2 minutes
/* and also here - your code */
}
}.run();
or, if your code is longer than just one method (readWebsite() in this case), and you don't want that to be duplicated:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
handler.postDelayed(this, 2 * 60 * 1000); // every 2 minutes
/* your longer code here */
}
}, 0); // first run instantly
(^ this one is just like the first example but has a 0ms delay before first run instead of 2 minutes)
(This answer is based on #Devashish Mamgain's one but I added too much details for an edit so I had to add a new one)
Try extending the Thread class, set a sleep time of 2000 millis and place your call into the run method. That should do it.
Execute multiple messages(Runnables) then he should use the Looper class which is responsible for creating a queue in the thread. For example, while writing an application that downloads files from the internet, we can use Looper class to put files to be downloaded in the queue. This will help you to perform async task in android...
HandlerThread hThread = new HandlerThread("HandlerThread");
hThread.start();
Handler handler = new Handler(hThread.getLooper());
final Handler handler1 = new Handler(hThread.getLooper());
final long oneMinuteMs = 60 * 1000;
Runnable eachMinute = new Runnable() {
#Override
public void run() {
Log.d(TAG, "Each minute task executing");
handler1.postDelayed(this, oneMinuteMs);
sendPostRequest();
}
};
// sendPostRequest();
// Schedule the first execution
handler1.postDelayed(eachMinute, oneMinuteMs);
You can use Time with Handler and TimerTask
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask backtask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
//To task in this. Can do network operation Also
Log.d("check","Check Run" );
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(backtask , 0, 20000); //execute in every 20000 ms*/
You can check logcat to verify whether is running or not using 'check' tag name
You could run a loop within the AsyncTask that sleeps for two seconds between doing the tasks. Something like this:
protected Result doInBackground (Params... params) {
while (!interrupted) {
doWork();
Thread.sleep(2000);
}
}

Problem getting timer to work after cancelling one iteration and starting another

I am stuck trying to get my timer to work, where I will do one countdown, then go back and do another.
So, on the second call to timer.scheduleAtFixedRate I get an IllegalStateException, but I am cancelling the TimerTask not the Timer.
What I want to do is count down twenty seconds, then ten seconds, then repeat, updating a text box each time, to inform the user what they should be doing.
One issue is that the countdown is faster than once/second.
04-22 01:34:57.118: DEBUG/TestHandler1(404): message called:2:null
04-22 01:34:57.709: DEBUG/TestHandler1(404): message called:3:null
04-22 01:34:57.899: DEBUG/TestHandler1(404): message called:4:null
04-22 01:34:58.198: DEBUG/TestHandler1(404): message called:5:null
Here is my exception:
04-22 01:35:48.529: ERROR/AndroidRuntime(404): java.lang.IllegalStateException: TimerTask is scheduled already
04-22 01:35:48.529: ERROR/AndroidRuntime(404): at java.util.Timer.scheduleImpl(Timer.java:574)
04-22 01:35:48.529: ERROR/AndroidRuntime(404): at java.util.Timer.scheduleAtFixedRate(Timer.java:530)
Here is the code I used for this attempt. When I tried to use a different timertask for each loop it was even worse behavior, as I put the new TimerTask block just before timer.scheduleAtFixedRate, so I went back to this version.
handler = new Handler() {
public void handleMessage(Message msg) {
counterText.setText((new Date()).toString() + " "
+ Integer.toString(cntr));
System.out.println("handleMessage");
}
};
timertask = new TimerTask() {
public void run() {
handler.sendEmptyMessage(0);
cntr++;
if (cntr > maxReps) {
timertask.cancel();
cntr = 0;
}
}
};
doneButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cntr = 0;
for (MyClass mclass : input.getLoop()) {
labelText.setText(mclass.getName());
for (int y = 0; y < 8; y++) {
maxReps = 20;
timer.scheduleAtFixedRate(timertask, 0, 1000);
maxReps = 10;
labelText.setText("Rest");
timer.scheduleAtFixedRate(timertask, 0, 1000);
}
}
}
});
Hopefully someone can point out a simple mistake that I made.
Above is a snippet of my code from the Activity, so I am including just what I think is needed to show where I am having a problem.
Given this article in the dev guide: http://developer.android.com/resources/articles/timed-ui-updates.html and a similar post here: http://cart.kolix.de/?p=1438 , I would suggest you to change the strategy and use handler.postDelayed(this, 2000);
But, specifically to the code, my guess is that it may get cancelled the wrong task. I don't really understand the rationale for having two calls to timer.scheduleAtFixedRate(timertask, 0, 1000); and setting maxReps = 20; first and then maxReps = 10; in the same loop, because the loop will not wait for the task to complete before continuing.
So, you are sending at least 16 calls to timer.scheduleAtFixedRate() and not all may get cancelled at the right time.
After experimenting with various methods, I finally settled on this solution.
In my OnCreate method I had this code, and it would go 20 seconds then exit.
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
String s = msg.getData().getString("counter");
counterText.setText(s);
Log.d("Activity.handleMessage", s);
}
};
final Runnable runnable = new Runnable() {
#Override
public void run() {
final long start = SystemClock.uptimeMillis();
while (true) {
Message m = new Message();
Bundle b = new Bundle();
b.putString("counter", Integer.toString(cntr));
m.setData(b);
handler.sendMessageDelayed(m, cntr * 1000);
if (cntr++ == maxReps) {
return;
}
}
}
};
doneButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
exerciseText.setText(model.getName());
counterText.setText("0");
maxReps = 20;
handler.postDelayed(runnable, 1000);
});
Part of my difficulty is not thinking about how Android works. I found various approaches that didn't work well.

How to change a TextView every second in Android

I've made a simple Android music player. I want to have a TextView that shows the current time in the song in minutes:seconds format. So the first thing I tried was to make the activity Runnable and put this in run():
int position = 0;
while (MPService.getMP() != null && position<MPService.duration) {
try {
Thread.sleep(1000);
position = MPService.getSongPosition();
} catch (InterruptedException e) {
return;
}
// ... convert position to formatted minutes:seconds string ...
currentTime.setText(time); // currentTime = (TextView) findViewById(R.id.current_time);
But that fails because I can only touch a TextView in the thread where it was created. So then I tried using runOnUiThread(), but that doesn't work because then Thread.sleep(1000) is called repeatedly on the main thread, so the activity just hangs at a blank screen. So any ideas how I can solve this?
new code:
private int startTime = 0;
private Handler timeHandler = new Handler();
private Runnable updateTime = new Runnable() {
public void run() {
final int start = startTime;
int millis = appService.getSongPosition() - start;
int seconds = (int) ((millis / 1000) % 60);
int minutes = (int) ((millis / 1000) / 60);
Log.d("seconds",Integer.toString(seconds)); // no problem here
if (seconds < 10) {
// this is hit, yet the text never changes from the original value of 0:00
currentTime.setText(String.format("%d:0%d",minutes,seconds));
} else {
currentTime.setText(String.format("%d:%d",minutes,seconds));
}
timeHandler.postAtTime(this,(((minutes*60)+seconds+1)*1000));
}
};
private ServiceConnection onService = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder rawBinder) {
appService = ((MPService.LocalBinder)rawBinder).getService();
// start playing the song, etc.
if (startTime == 0) {
startTime = appService.getSongPosition();
timeHandler.removeCallbacks(updateTime);
timeHandler.postDelayed(updateTime,1000);
}
}
what about this:
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
//your code
}
}, delay, period);
Use a Timer for this (instead of a while loop with a Thread.Sleep in it). See this article for an example of how to use a timer to update a UI element periodically:
Updating the UI from a timer
Edit: updated way-back link, thanks to Arialdo: http://web.archive.org/web/20100126090836/http://developer.android.com/intl/zh-TW/resources/articles/timed-ui-updates.html
Edit 2: non way-back link, thanks to gatoatigrado: http://android-developers.blogspot.com/2007/11/stitch-in-time.html
You have to use a handler to handle the interaction with the GUI. Specifically a thread cannot touch ANYTHING on the main thread. You do something in a thread and if you NEED something to be changed in your main thread, then you call a handler and do it there.
Specifically it would look something like this:
Thread t = new Thread(new Runnable(){
... do stuff here
Handler.postMessage();
}
Then somewhere else in your code, you do
Handler h = new Handler(){
something something...
modify ui element here
}
Idea its like this, thread does something, notifies the handler, the handler then takes this message and does something like update a textview on the UI thread.
This is one more Timer example and I'm using this code in my project.
https://stackoverflow.com/a/18028882/1265456
I think the below blog article clearly gives a very nice solution. Especially, if you are a background service and want to regularly update your UI from this service using a timer-like functionality.
It really helped me, much more than the 2007 blog link posted by MusiGenesis above.
https://www.websmithing.com/2011/02/01/how-to-update-the-ui-in-an-android-activity-using-data-from-a-background-service/

Categories

Resources