I am using java and android studio. I am trying to close an activity I set up with a scheduleatfixedrate when I pause or destroy the app. The problem is I cannot get the code to resolve the timer and tasknew reference I use to set up the scheduleatrfixedrate in the onpause and onDestroy methods. Below is my code:
#Override
protected void onResume() {
super.onResume();
TimerTask tasknew = new readDevice();
Timer timer = new Timer();
timer.scheduleAtFixedRate(tasknew, 1000, 500);
}
// Activity paused
#Override
protected void onPause() {
super.onPause();
tasknew.cancel();
timer.purge();
}
Without being able to cancel the timer, it just keeps running in the background.
Update:
I solved the problem which I update my solution in case someone else new to java has this problem. I found out all I had to do is move the statement creating tasknew and timer outside of onResume and moved the cancel and purge to the onDestroy method. Below is my working code.
public class DeviceControlActivity extends Activity {
private TimerTask tasknew = new readDevice();
private Timer timer = new Timer();
#Override
protected void onResume() {
super.onResume();
timer.scheduleAtFixedRate(tasknew, 1000, 500);
}
#Override
protected void onDestroy() {
super.onDestroy();
tasknew.cancel();
timer.purge();
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
}
I guess it would have been enough to create a daemon Timer:
new Timer(true)
So, the timer would end when the rest of non-daemon threads of the program end.
Related
Here is my fixed rate timer code. Can i pause this timer while activity goes in onPause(); . If so then what would you suggest me put in onPause(); method and timer should start work as app comes to onResume();:
//Declare the timer
t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// code here
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
20000,
//Set the amount of time between each execution (in milliseconds)
40000);
You can use Timer.cancel()
Terminates this timer, discarding any currently scheduled tasks. Does not interfere with a currently executing task (if it exists). Once a timer has been terminated, its execution thread terminates gracefully, and no more tasks may be scheduled on it.
Declare the timer as global
t = new Timer();
Try this
#Override
protected void onPause() {
super.onPause();
t.cancel();
}
timer should start work as app comes to onResume();:
You need to start Timer in onResume()
Try this
#Override
protected void onResume() {
super.onResume();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// code here
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
20000,
//Set the amount of time between each execution (in milliseconds)
40000);
}
I have a fragment where a timer starts running immediately when you initialize and it shows a different image every 6 seconds.
I haven't fully figured out how this timer thing works, but somehow i got it running and i understand the timer runs in a different thread... not even sure what exactly that means : )
But the timer causes a crash when i load a different fragment. so i guess i have to CANCEL the timer when the activity is closed?
That brings me to two questions.
1) Can i run myTimer.cancel from anywhere? if yes, how do i run it from my main activity or from other fragments.
2) is there something like onCloseActivity i can use for this fragment. so i can cancel my timer as soon as i leave the fragment?
this is how i start my timer:
// timer
Timer myTimer;
/////////////////////
/////// timer ///////
/////////////////////
private void runTimer() {
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 5000, 5000);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
// next image if THIS one is loaded
nextImage();
}
};
private void TimerMethod() {
getActivity().runOnUiThread(Timer_Tick);
}
And here is my error:
getActivity().runOnUiThread(Timer_Tick);
causes the error when i load a different fragment.
E/AndroidRuntime: FATAL EXCEPTION: Timer-1
Process: com.murmurcalgary.murmurcalgaryevolvd, PID: 8668
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.FragmentActivity.runOnUiThread(java.lang.Runnable)' on a null object reference
at com.murmurcalgary.murmurevolvd.fragments.EventsFragment.TimerMethod(EventsFragment.java:92)
at com.murmurcalgary.murmurevolvd.fragments.EventsFragment.access$000(EventsFragment.java:45)
at com.murmurcalgary.murmurevolvd.fragments.EventsFragment$1.run(EventsFragment.java:77)
at java.util.Timer$TimerImpl.run(Timer.java:284)
You can use fragment's life-cycle methods for stopping the timer.
Override onStop() method in fragment and then cancel the timer task inside that method.
#Override
public void onStop() {
super.onStop();
if(timerTask != null){
timerTask.cancel();
//cancel timer task and assign null
}
}
In my onCreate method in my activity i call a method from an object and pass the methods value as 1 which means to start a timer in the objects class. However I want to stop the timer whenever the app closes, loses focus or someone pressed the back button on their device and exited the app. I tried doing this below my onCreate method with an onPause, onStop, onDestroy and entered the methods value as 2 for the object which means to cancel the timer. However my problem is that whenever someone presses the back button on their device and then goes back in to the app the same timer is running twice because the app did not cancel the timer in the onStop, onPause or onDestroy. Why didn't the onStop, onPause and onDestroy stop the timer and how do i make it stop the timer so two arent running when the app is reopened?
Activity below
Ship mShip = new Ship(0,0,0);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mShip.timerStart(1);
}
#Override
public void onPause()
{
super.onPause();
mShip.timerStart(2);
}
#Override
public void onStop()
{
super.onStop();
mShip.timerStart(2);
}
#Override
public void onDestroy()
{
super.onDestroy();
mShip.timerStart(2);
}
Ship Class below
public static int counter = 0;
public static int counterPerSec = 5;
TimerClass startTimer = (TimerClass) new TimerClass(2000,1000)
{
#Override
public void onFinish() {
counter += counterPerSec;
this.start();
}
};
public void timerStart(int x) {
if(x == 1)
{
startTimer.start();
}
if(x == 2)
{
startTimer.cancel();
}
}
Timer Class
public class TimerClass extends CountDownTimer {
public TimerClass(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override // when timer is finished
public void onFinish() {
this.start();
}
#Override // on every tick of the timer
public void onTick(long millisUntilFinished) {
}
}
I can not see, why your timer is not canceled. But there is another bug in your code: You can not pause and resume a countdown timer by calling resume and start.
If your time gets canceled, you should save the old timer vaules. And if your timer has to be resumed, you can create a new timer with the old timer values. See: Android: How to pause and resume a Count Down Timer?
To your question: Can you debug and check if onPause, onStop, onDestroy is called? Is there any exception thrown? Do you have any compile warnings?
Last important question: How do you know that two timers are running?
Well, I think I can correctly assume that onPause, onStop, and onDestroy are executing, so I would venture to guess that there is a bug in your TimerClass class.
I am trying to get a timer to run in a separate thread.
I have the following declaration before my onCreate function:
TimerTask scanTask;
Timer t = new Timer();
Then the following code within onCreate:
Runnable runnable = new Runnable() {
#Override
public void run() {
scanTask = new TimerTask() {
#Override
public void run() {
System.out.println("timer test");
}
};
t.schedule(scanTask, 0, 5000);
CountDownTimer waitTimer;
waitTimer = new CountDownTimer(20000,300) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
t.cancel();
System.out.println("Timer stopped");
}
}.start();
}
};
Thread periodic_scan = new Thread(runnable);
periodic_scan.start();
However, when I run the app, it crashes and gives me the error:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
I'm not sure I completely understand why this error is occurring. Is it something to do with the UI thread? Also, I'm not sure whether the way I've tried to implement this is correct. This is my first time trying to deal with threads in Android.
you can use HandlerThread like
HandlerThread handlerThread = new HandlerThread("name");
handlerThread.start();
Handler threadHandler = new Handler(handlerThread.getLooper(),new Callback() {
public boolean handleMessage(Message msg) {
return true;
}
});
I ended up changing the code a bit and decided to use a Thread class:
class TimerThread extends Thread {
TimerTask scanTask;
Timer t = new Timer();
#Override
public void run() {
Looper.prepare();
scanTask = new TimerTask() {
public void run() {
System.out.println("timer test");
}
};
t.schedule(scanTask, 0, 5000);
CountDownTimer waitTimer;
waitTimer = new CountDownTimer(20000,300) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
t.cancel();
System.out.println("Timer stopped");
}
}.start();
Looper.loop();
}
}
In onCreate I used the following:
new TimerThread().start();
The program now works without any errors, however the only problem now is that there is a noticeable 2-3 second lag when the program loads up before the UI renders to the screen.
I'm not sure why this is happening if the timer function I am using is running on a separate thread, unless I've missed something here...
If you create a handler (or any class you call creates a handler) it needs to be in a Thread that has a Looper on it, and has called Looper.prepare(). Either TimerTask or CountDownTimer is doing that. How to fix it depends on where you want the events to be posted to. If you want them on the UI thread, you'll have to create the handler on the UI thread. If you want them on this thread, then you need to call Looper.prepare and Looper.loop at some point.
The UI thread already has a looper (the framework starts it for you) so its always ok to make handlers there.
Im using a Timer to continuously update a TextView, but I'm having trouble restarting the timer during the onResume() method. I use timer.cancel() in the onPause() and onDestroy() methods, but how do I restart the timer in onResume()?
This is my timer code...
int delay = 1000;
int period = 1000;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
//I update the TextView here
}
}, delay, period);
An easier alternative is to use the Handler class. I wouldn't recommend the Timer class because it has no bearing on the life cycle of your Activity and you will have to worry about any potential threading problems yourself. The beauty of using the Handler is that all your callbacks will be on the main thread (so no threading issues to worry about). The following is a simple example on how to do this.
#Override
protected void onCreate(Bundle savedInstanceState)
{
....
mHandler = new Handler();
}
#Override
protected void onResume()
{
mHandler.postDelayed(myRunnable, UPDATE_RATE);
}
#Override
protected void onPause()
{
mHandler.removeCallbacks(myRunnable);
}
private final Runnable myRunnable= new Runnable() {
#Override
public void run()
{
//Do task
mHandler.postDelayed(myRunnable, UPDATE_RATE);
}
}
You dont restart the timer. Instead use a new timer i.e inside onResume() create a new timer. As you are no longer using the previous one, garbage collection will take care of it. So in onResume() use the following code:
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
//update the TextView here
}
}, delay, period);