I am currently trying to set up a WiFi Scan in my Android application that scans for WiFi access points every 30 seconds.
I have used Timer and TimerTask to get the scan running correctly at the intervals which I require.
However I want to be able to stop and start the scanning when the user presses a button and I am currently having trouble stopping and then restarting the Timer and TimerTask.
Here is my code
TimerTask scanTask;
final Handler handler = new Handler();
Timer t = new Timer();
public void doWifiScan(){
scanTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
wifiManager.scan(context);
Log.d("TIMER", "Timer set off");
}
});
}};
t.schedule(scanTask, 300, 30000);
}
public void stopScan(){
if(scanTask!=null){
Log.d("TIMER", "timer canceled");
scanTask.cancel();
}
}
So the Timer and Task start fine and the scan happens every 30 seconds however I cant get it to stop, I can stop the Timer but the task still occurs and scanTask.cancel() doesn't seem to work either.
Is there a better way to do this? Or am I missing something in the Timer/TimerTask classes?
You might consider:
Examining the boolean result from calling cancel() on your task, as it should indicate if your request succeeds or fails
Try purge() or cancel() on the Timer instead of the TimerTask
If you do not necessarily need Timer and TimerTask, you can always use postDelayed() (available on Handler and on any View). This will schedule a Runnable to be executed on the UI thread after a delay. To have it recur, simply have it schedule itself again after doing your periodic bit of work. You can then monitor a boolean flag to indicate when this process should end. For example:
private Runnable onEverySecond=new Runnable() {
public void run() {
// do real work here
if (!isPaused) {
someLikelyWidget.postDelayed(onEverySecond, 1000);
}
}
};
using your code, instead of
scanTask.cancel();
the correct way is to cancel your timer (not timerTask):
t.cancel();
The Android documentation says that cancel() Cancels the Timer and all scheduled tasks. If there is a currently running task it is not affected. No more tasks may be scheduled on this Timer. Subsequent calls do nothing. Which explains the issue.
Related
I have created a runnable thread to change/swipe the View Pager position through auto-looping in homepage.
In my app, I want to stop this thread when logout button is clicked.
I have tried removecallback method but still the app crashes sometimes.
Any other solution?
Below is my Code:
final Handler offers1Handler = new Handler();
Runnable offers1Runnable;
private void setLooping() {
offers1Runnable = () -> scrollPager(binding.contentHome.offers1ViewPager);
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
offers1Handler.postDelayed(offers1Runnable, 1000);
}
},500, 3000);
}
}
private void onLogout(){
offers1Handler.removeCallbacks(offers1Runnable);
}
if you want to cancel the timer by yourself, you can use cancel method.
the Runnable is not a thread, it just has a method run. the Timer is A facility for threads, which to schedule tasks for future execution in a background thread. if you want to cancel, you actually want to cancel the Timer. As the document describes:
If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the timer's cancel method.
if you call the cancel method. its execution thread terminates gracefully, and no more tasks may be scheduled on it.
I write an application that connects to server and sends him ping commands, server answer with pong commands.
I want to implement connection timeout mechanism. I think it will be following:
Client send ping and start timer with timertask and delay
When client receive pong, timertask is cancelled.
Also, I want to optimize memory. So, not to recreate TimerTask every time I send ping command. I try code below:
private final Timer mSystemLogoutTimer = new Timer();
private final TimerTask mLogoutTask = new TimerTask() {
#Override
public void run() {
mMessageInterface.onConnectionTimeout();
cancel();
}
};
private void ping() {
sendRequest(RequestBuilder.formPing());
mSystemLogoutTimer.schedule(mLogoutTask, CoreConst.PING_ANSWER_DELAY);
}
private void onPong() {
mLogoutTask.cancel();
}
But I get following error when try to schedule TimerTask second time:
java.lang.IllegalStateException: TimerTask is scheduled already
at java.util.Timer.scheduleImpl(Timer.java:572)
at java.util.Timer.schedule(Timer.java:459)
I don't understand, because I call cancel() on TimerTask.
Please tell me what I am doing wrong.
Thank you for answers!
TimerTask.cancel() does not necessarily prevent the execution of the task. According to the SDK documentation, it returns true when the execution was actually prevented, false otherwise.
Looks like this it what happens with your code as the first time true is returned, but not the second, leading an IllegalStateException to be thrown when calling Timer.schedule() right after.
You should check TimerTask.cancel()'s return code, and recreate your TimerTask when false is returned: the TimerTask is burnt and cannot be reused at that stage.
I'm calling my TimerTask (m_timer) upon a button click:
m_timer.schedule(m_progressUpdater, 0, 500);
Which kicks off my run method:
#Override
public void run() {
//do some stuff
progressBar.setProgress(currentProgress);
if (progress >= 100) {
handler.post(new Runnable() {
#Override
public void run() {
CompleteTask();
}
});
}
}
I can call this once and it works perfectly. When I call it again, my app stops responding. I'm thinking that I need to cancel the task in my CompleteTask() method, but I've tried cancelling both the TimerTask and the Timer, and it still crashes. Anyone know what the problem might be?
Have you tried creating new TimerTask instance for the second call? And by the way, don't cancel the timer otherwise it will cancel all of its task. And what did the log say?
When you reschedule a Timer, it throws:
java.lang.IllegalStateException: TimerTask is scheduled already
It seems that you can only use a timer for once.
In order to reschedule a Timer, you need to simply create a new instance of it, each time. like the following:
// if you have already started a TimerTask,
// you must(?) terminate the timer before rescheduling it again.
if(m_timer != null)
m_timer.cancel();
m_timer = new Timer();
m_progressUpdater = new myTimerTask();
m_timer.schedule(m_progressUpdater, 0, 500);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm developing an application which sends a message to a specific number in a specific period of time. The problem is that it continues sending that message after that period of time. How would I stop the timer after that specific time in order to stop sending that message?
CountDownTimer waitTimer;
waitTimer = new CountDownTimer(60000, 300) {
public void onTick(long millisUntilFinished) {
//called every 300 milliseconds, which could be used to
//send messages or some other action
}
public void onFinish() {
//After 60000 milliseconds (60 sec) finish current
//if you would like to execute something when time finishes
}
}.start();
to stop the timer early:
if(waitTimer != null) {
waitTimer.cancel();
waitTimer = null;
}
and.. we must call "waitTimer.purge()" for the GC. If you don't use Timer anymore, "purge()" !! "purge()" removes all canceled tasks from the task queue.
if(waitTimer != null) {
waitTimer.cancel();
waitTimer.purge();
waitTimer = null;
}
In java.util.timer one can use .cancel() to stop the timer and clear all pending tasks.
We can schedule the timer to do the work.After the end of the time we set the message won't send.
This is the code.
Timer timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//here you can write the code for send the message
}
}, 10, 60000);
In here the method we are calling is,
public void scheduleAtFixedRate (TimerTask task, long delay, long period)
In here,
task : the task to schedule
delay: amount of time in milliseconds before first execution.
period: amount of time in milliseconds between subsequent executions.
For more information you can refer:
Android Developer
You can stop the timer by calling,
timer.cancel();
I had a similar problem: every time I push a particular button, I create a new Timer.
my_timer = new Timer("MY_TIMER");
my_timer.schedule(new TimerTask() {
...
}
Exiting from that activity I deleted the timer:
if(my_timer!=null){
my_timer.cancel();
my_timer = null;
}
But it was not enough because the cancel() method only canceled the latest Timer. The older ones were ignored an didn't stop running. The purge() method was not useful for me.
I solved the problem just checking the Timer instantiation:
if(my_timer == null){
my_timer = new Timer("MY_TIMER");
my_timer.schedule(new TimerTask() {
...
}
}
It says timer() is not available on android? You might find this article useful.
http://developer.android.com/resources/articles/timed-ui-updates.html
I was wrong. Timer() is available. It seems you either implement it the way it is one shot operation:
schedule(TimerTask task, Date when) // Schedule a task for single execution.
Or you cancel it after the first execution:
cancel() // Cancels the Timer and all scheduled tasks.
http://developer.android.com/reference/java/util/Timer.html
I had a similar problem and it was caused by the placement of the Timer initialisation.
It was placed in a method that was invoked oftener.
Try this:
Timer waitTimer;
void exampleMethod() {
if (waitTimer == null ) {
//initialize your Timer here
...
}
The "cancel()" method only canceled the latest Timer. The older ones were ignored an didn't stop running.
Hello I am building an application that is going to execute a block of code at fixed periods of time (e.g. every 30 minutes). I would like that period to be strict,what I mean is that I would like to be guaranteed that the period will be 30 minutes and not 28 minutes or whenever the os whants to execute it.
I have a Timer object and use it as follows:
timer=new Timer();
timer.scheduleAtFixedRate(new GetLastLocation(), 0, this.getInterval());
where GetLastLocation is the handler class wich extends TimerTask.
This works fine,but I would like to be able to change the interval,what I am currently doing is using timer.scheduleAtFixedRate twice and changing the interval parameter to lets say a newInterval but I think that this is just having two timers execute every interval and new
Interval now, am I correct?
also I have tries cancelling the timer and then using the the method scheduleAtFixedRate() but this throws an exception as stated in the documentation.
what can I do to fix this?
regards maxsap
you can not schedule on a timer which was already cancelled or scheduled. You need to create a new timer for that.Timer timer;
synchronized void setupTimer(long duration){
if(timer != null) {
timer.cancel();
timer = null;
}
timer = new Timer();
timer.scheduleAtFixedRate(new GetLastLocation(), 0, duration);
}Now you can call setupTimer whenever you want to change the duration of the timer.PS: In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution will be exactly the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate).
Define your task inside a TimerTask (as you did) and schedule the timer.
public final void checkFunction(){
t = new Timer();
tt = new TimerTask() {
#Override
public void run() {
//Execute code...
}
};
t.schedule(tt, 10*1000); /* Run tt (your defined TimerTask)
again after 10 seconds. Change to your requested time. */
}
Just execute the function wherever you want, for example in onCreate or in onResume/onStart.
You can also use handler instead of timertask.
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if(what.msg==1)
{
what.msg==2;
}
}
};
mHandler.sendEmptyMessageDelayed(1, 10* 1000);//10*1000 10 sec.specify your time