Closing a SWT application after certain time of inactivity - java

I'm trying to close a SWT application after certain period of inactive time. I'm finding difficulty in calculating the inactivity period.All that I've tried just shuts the application after the specified amount of time, irrespective of whether I'm still working on the Application.
Below is the code of what I've tried
Timer timer = new Timer();
display.asyncExec(new Runnable(){
public void run() {
while(!shell.isDisposed()){
if (!display.readAndDispatch()){ //if the system is idle
timer.schedule(new TimerTask() { //schedule timer which will trigger after 1min.
#Override
public void run() {
logout();
}
}, 60000);
}
else{ // reschedule the timer
timer.cancel();
Timer timer = new Timer();
}
}
}
});
with this I'm just able to logout after 1 min even if the user is performing something. Is there a way we can check the inactivity time in SWT ?

You can use Display.addFilter to listen for various events that make the app 'active'. Use Display.timerExec to run code in the UI thread repeatedly to check the time since the last event.
Maybe something like:
private Instant lastActive;
....
lastActive = Instant.now();
final Listener listener = new Listener()
{
#Override
public void handleEvent(final Event event)
{
lastActive = Instant.now();
}
};
display.addFilter(SWT.MouseMove, listener);
display.addFilter(SWT.KeyDown, listener);
// TODO more filters if required
final Runnable timer = new Runnable()
{
#Override
public void run()
{
final Instant now = Instant.now();
if (ChronoUnit.SECONDS.between(lastActive, now) > xxx) { // Number of inactive seconds here
System.out.println("inactive"); // Inactive code here
}
else {
display.timerExec(1000, this);
}
}
};
display.timerExec(1000, timer);
... create/open shell ...
while (!shell.isDisposed())
{
if (!display.readAndDispatch())
display.sleep();
}

Related

Java - Reusing Timer Object after calling cancel

I have an application in Java where I need to schedule a TimerTaskwhich will be executed after 500ms , however if a certain event occurs, I must reset the timer for this task (so that we must wait another 500ms for it to execute). I have a timer declared for the whole class. I use the following code:
public static void main(String[] args) {
if (curr_pck == my_pck) {
timer.cancel();
timer.purge();
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
myTask();
}
}, 500);
}
}
public static void myTask() {
timer.cancel();
timer.purge();
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
myTask();
}
}, 500);
//EXECUTE CODE WHICH ISN'T RELEVANT TO THE QUESTION
}
I know that if I use timer.cancel() I can't reuse the timer object, however I thought reinitialising it in the line timer = new Timer() should solve this issue. Is there any way around this?
EXCEPTION on line timer.schedule(new TimerTask() { inside myTask() function:
java.lang.IllegalStateException: Timer already cancelled.
Create a class Timerr with the appropriate methods. Then access it as if it were a normal timer.
public class Timerr
{
private Timer timer;
public Timerr()
{
timer = new Timer();
start();
}
public void start()
{
timer.schedule(new TimerTask()
{
#Override
public void run()
{
System.out.println("hi");
}
}, 500);
}
public void reset()
{
timer.cancel();
timer.purge();
start();
}
}
Create instance
private Timerr timer = new Timerr();
Do your reset
if(condition)
{
timerr.reset();
}
You may want to check out Java's Swing timer. It works somewhat differently and you may have to write an internal class or an actionlistener, but the Swing timer includes .stop() and .restart(), which seem like they would work better in your application.

Reuse a timer timertask Java

Soo created a timer using extending timertask.
label_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
label_1.setVisible(false);
label_2.setVisible(true);
timer.purge();
class MyTimeTask extends TimerTask
{
public void run(){
genReelNumbers();
laa++;
if(laa==50){
timer.cancel();
timer.purge();
laa=0;
label_1.setVisible(true);
label_2.setVisible(false);}}}
timer.purge();
timer.schedule(new MyTimeTask(), 0, 50);}});
But im getting a error with the timer already canceled! As you can see i already tried to use the purge(), soo it cancels the "canceled" timers (dont know if that does make any sence). I want to use this timer each time that i press on the label! Any ideas?
First and foremost, this looks to be a Swing application, and if so, you shouldn't be using java.util.Timer and java.util.TimerTask since Swing is single-threaded, and the two classes above create a new thread or threads to achieve their actions, meaning that important code that should be called on the Swing event thread will not be called on this thread. This this risks causing pernicious intermittent and hard to debug threading exceptions to be thrown. Instead use a javax.swing.Timer. Then to stop this timer, simply call stop() on it, and to restart it, simply call start() on it. For more on this, please read: How To Use Swing Timers.
For example, I'm not 100% sure what you're code is supposed to be doing, but it could look something like:
// warning: code not compile- nor run-tested
label_1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
label_1.setVisible(false);
label_2.setVisible(true);
// assuming a javax.swing.Timer field named timer
if (timer != null && timer.isRunning()) {
// if the timer is not null and it's running, stop it:
timer.stop();
}
// TIMER_DELAY is an int constant that specifies the delay between "ticks"
timer = new Timer(TIMER_DELAY, new ActionListener() {
#Override // this method will be called repeatedly, every TIMER_DELAY msecs
public void actionPerformed(ActionEvent e) {
genReelNumbers();
laa++;
if(laa==50){
timer.stop();
// timer.purge();
laa=0;
label_1.setVisible(true);
label_2.setVisible(false);
}
}
});
timer.start();
}
});
after canceling the timer you have no other choice than creating a new object....
I followed the #Hovercraft advice and changed to javax.swing.Timer
It turned out like this:
//The variable "taxa" is the amount of times that i want it to do the task
javax.swing.Timer time1 = new javax.swing.Timer(taxa, new ActionListener() {
public void actionPerformed(ActionEvent e) {
genReelNumbers();
}
});
//starts the timer
time1.start();
//New timertask
TimerTask tt = new TimerTask() {
#Override
public void run() {
//stops the timer
time1.stop();
label_2.setVisible(false);
label_1.setVisible(true);
verificarodas();
}
};
Timer time = new Timer(true);
// the 2000 is how long i want to do the task's
//if i changed to 3000 it would take 3 seconds (remember it has to be a value on miliseconds) to do the 15 times, and soo on
time.schedule(tt, 2000);

Scheduling java process for a specific time interval with a given delay

We want to schedule a java process to run till a specific time interval. Currently I am thinking to using TimerTask to schedule this process. In the start of every loop, will check the current time and then compare with the given time and stop the process if the time is elapsed.
Our code is something like below:
import java.util.Timer;
import java.util.TimerTask;
public class Scheduler extends TimerTask{
public void run(){
//compare with a given time, with getCurrentTime , and do a System.exit(0);
System.out.println("Output");
}
public static void main(String[] args) {
Scheduler scheduler = new Scheduler();
Timer timer = new Timer();
timer.scheduleAtFixedRate(scheduler, 0, 1000);
}
}
Is there a better approach for this?
Instead of checking if the time limit has been reached in every single iteration you could schedule another task for the said time limit and call cancel on your timer.
Depending on the complexity you might consider using a ScheduledExecutorService such as ScheduledThreadPoolExecutor. See in this answer when and why.
Simple working example with timer:
public class App {
public static void main(String[] args) {
final Timer timer = new Timer();
Timer stopTaskTimer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
System.out.println("Output");
}
};
TimerTask stopTask = new TimerTask() {
#Override
public void run() {
timer.cancel();
}
};
//schedule your repetitive task
timer.scheduleAtFixedRate(task, 0, 1000);
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse("2015-06-09 14:06:30");
//schedule when to stop it
stopTaskTimer.schedule(stopTask, date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
You can use RxJava, a very powerful library for reactive programming.
Observable t = Observable.timer(0, 1000, TimeUnit.MILLISECONDS);
t.subscribe(new Action1() {
#Override
public void call(Object o) {
System.out.println("Hi "+o);
}
}
) ;
try {
Thread.sleep(10000);
}catch(Exception e){ }
You can even use the lambda syntax:
Observable t = Observable.timer(0, 1000, TimeUnit.MILLISECONDS);
t.forEach(it -> System.out.println("Hi " + it));
try {
Thread.sleep(10000);
}catch(Exception e){ }

How to change android timer period?

I am writing simple game, where some action must accelerating during the process. The question is how to change timer's period?
timer = new Timer();
timerTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
//
// I need to change timer's period here
//
}
});
}
};
timer.schedule(timerTask, 0, period);
Will be glad to hear any advices.
I assume that you are performing some logic within the run() method of the TimerTask.
I think a simpler way to go about this would be to use a Handler. This is possibly more idiomatic for Android:
private final Handler mHandler = new Handler();
private final Runnable mTask = new Runnable() {
#Override
public void run() {
// Do your logic.
// Now post again.
mHandler.postDelayed(mTask, /* choose a new delay period */);
}
};
public void init() {
delay = 1000L; // 1 second.
mHandler.postDelayed(mTask, delay);
}

Pausing/stopping and starting/resuming Java TimerTask continuously?

I have one simple question regarding Java TimerTask. How do I pause/resume two TimerTask tasks based on a certain condition? For example I have two timers that run between each other. When a certain condition has been met inside the task of first timer, the first timer stops and starts the second timer, and the same thing happens when a certain condition has been met inside the task of second timer. The class below shows exactly what I mean:
public class TimerTest {
Timer timer1;
Timer timer2;
volatile boolean a = false;
public TimerTest() {
timer1 = new Timer();
timer2 = new Timer();
}
public void runStart() {
timer1.scheduleAtFixedRate(new Task1(), 0, 1000);
}
class Task1 extends TimerTask {
public void run() {
System.out.println("Checking a");
a = SomeClass.getSomeStaticValue();
if (a) {
// Pause/stop timer1, start/resume timer2 for 5 seconds
timer2.schedule(new Task2(), 5000);
}
}
}
class Task2 extends TimerTask{
public void run() {
System.out.println("Checking a");
a = SomeClass.getSomeStaticValue();
if (!a) {
// Pause/stop timer2, back to timer1
timer1.scheduleAtFixedRate(new Task1(), 0, 1000);
}
// Do something...
}
}
public static void main(String args[]) {
TimerTest tt = new TimerTest();
tt.runStart();
}
}
So my question is, how do I pause timer1 while running timer2 and vice versa while timer2 is running? Performance and timing is my main concern as this needs to be implemented inside another running thread. By the way I am trying to implement these concurrent timers on Android.
Thanks for your help!
From TimerTask.cancel():
Note that calling this method from
within the run method of a repeating
timer task absolutely guarantees that
the timer task will not run again.
So once cancelled, it won't ever run again. You'd be better off instead using the more modern ScheduledExecutorService (from Java 5+).
Edit: The basic construct is:
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(runnable, 0, 1000, TimeUnit.MILLISECONDS);
but looking into it there's no way of cancelling that task once its started without shutting down the service, which is a bit odd.
TimerTask might be easier in this case but you'll need to create a new instance when you start one up. It can't be reused.
Alternatively you could encapsulate each task as a separate transient service:
final ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
Runnable task1 = new Runnable() {
public void run() {
a++;
if (a == 3) {
exec.shutdown();
exec = Executors.newSingleThreadScheduledExecutor();
exec.scheduleAtFixedRate(task2, 0, 1000, TimeUnit.MILLISECONDS)
}
}
};
exec.scheduleAtFixedRate(task1, 0, 1000, TimeUnit.MILLISECONDS);
easiest solution i found: just add a boolean in the run code in the timer task, like so:
timer.schedule( new TimerTask() {
public void run() {
if(!paused){
//do your thing
}
}
}, 0, 1000 );
If you have already canceled one timer, you can't re-start it, you'll have to create a new one.
See this answer, it contains a video and the source code how I did something similar.
Basically there are two method: pause and resume
In pause:
public void pause() {
this.timer.cancel();
}
In resume:
public void resume() {
this.timer = new Timer();
this.timer.schedule( aTask, 0, 1000 );
}
That makes the perception of pause/resume.
If your timers perform different actions based on the state of the application you may consider use the StatePattern
Fist define a abstract state:
abstract class TaskState {
public void run();
public TaskState next();
}
And provide as many states as you like. The key is that one state leads you to another.
class InitialState extends TaskState {
public void run() {
System.out.println( "starting...");
}
public TaskState next() {
return new FinalState();
}
}
class FinalState extends TaskState {
public void run() {
System.out.println("Finishing...");
}
public TaskState next(){
return new InitialState();
}
}
And then you change the state in your timer.
Timer timer = new Timer();
TaskState state = new InitialState();
timer.schedule( new TimerTask() {
public void run() {
this.state.run();
if( shouldChangeState() ) {
this.state = this.state.next();
}
}
}, 0, 1000 );
Finally, if what you need is to perform the same thing, but at different rates, you may consider using the TimingFramework. It is a bit more complex but let's you do cool animations, by allowing the painting of certain component take place at different rates ( instead of being linear )
In my opinion, this is somewhat misguided. If your code needs time guarantees, you can't use Timer anyway, nor would you want to. "This class does not offer real-time guarantees: it schedules tasks using the Object.wait(long) method."
The answer, IMHO, is that you don't want to pause and restart your timers. You just want to suppress their run methods from doing their business. And that's easy: you just wrap them in an if statement. The switch is on, they run, the switch is off, they miss that cycle.
Edit: The question has shifted substantially from what it was originally, but I'll leave this answer in case it helps anyone. My point is: if you don't care when your event fires in the N millisecond span (just that it doesn't EXCEED once every N milliseconds), you can just use conditionals on the run methods. This is, in fact, a very common case, especially when N is less than 1 second.
Reviewing your source code, here are the changes ( which pretty much validate my previous answer )
In task1:
// Stop timer1 and start timer2
timer1.cancel();
timer2 = new Timer(); // <-- just insert this line
timer2.scheduleAtFixedRate(new Task2(), 0, 1000);
and in task2:
// Stop timer2 and start timer1
timer2.cancel();
timer1 = new Timer(); // <-- just insert this other
timer1.scheduleAtFixedRate(new Task1(), 0, 1000);
It runs on my machine:
Android won't reuse a TimerTask that has already been scheduled once. So it's necessary to reinstantiate both the Timer and TimerTask, for example like this in a Fragment:
private Timer timer;
private TimerTask timerTask;
public void onResume ()
{
super.onResume();
timer = new Timer();
timerTask = new MyTimerTask();
timer.schedule(timerTask, 0, 1000);
}
public void onPause ()
{
super.onPause();
timer.cancel(); // Renders Timer unusable for further schedule() calls.
}
I am able to stop a timer and a task using following code:
if(null != timer)
{
timer.cancel();
Log.i(LOG_TAG,"Number of cancelled tasks purged: " + timer.purge());
timer = null;
}
if(task != null)
{
Log.i(LOG_TAG,"Tracking cancellation status: " + task.cancel());
task = null;
}
Timer timer1;
private boolean videoCompleteCDR=false;
private boolean isVideoPlaying=false;
int videoTime=0;
private int DEFAULT_VIDEO_PLAY_TIME = 30;
#Override
public View onCreate(){
isVideoPlaying = true; //when server response is successfully
}
#Override
public void onPause() {
super.onPause();
if(isVideoPlaying ) {
if(this.timer1 !=null) {
this.timer1.cancel();
}
}
}
#Override
public void onResume() {
super.onResume();
if(isVideoPlaying && !videoCompleteCDR) {
callTimerTask();
}
}
#Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
printLog( "GameFragment visible ");
if(isVideoPlaying && !videoCompleteCDR) {
callTimerTask();
}
} else {
printLog("GameFragment in visible ");
if(isVideoPlaying) {
if(this.timer1 !=null) {
this.timer1.cancel();
}
}
}
}
private void callTimerTask() {
// TODO Timer for auto sliding
printLog( "callTimerTask Start" );
timer1 = new Timer();
timer1.schedule(new TimerTask() {
#Override
public void run() {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (getActivity() == null) {
return;
}
videoTime++;
if(DEFAULT_VIDEO_PLAY_TIME ==videoTime){
videoCompleteCDR=true;
Log.e("KeshavTimer", "callTimerTask videoCompleteCDR called.... " +videoTime);
destroyTimer();
}
Log.e("KeshavTimer", "callTimerTask videoTime " +videoTime);
}
});
} else {
printLog("callTimerTask getActivity is null ");
}
}
}, 1000, 1000);
// TODO 300, 2000;
}
private void destroyTimer(){
this.timer1.cancel();
}

Categories