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.
Related
I have this code in android studio:
The question is that if I give the button back and the main activity takes me, that is going to continue executing.
How do I make it so that once it's behind, it does not run what's in the onfinished?
new CountDownTimer (40000,1000) {
#Override
public void onTick(long l)
{
crono.setText("00:"+l/1000);
if(contador==10)
{
}
}
#Override
public void onFinish()
{
if(value.equals("tiempo"))
{
crono.setText("00:00");
}
else
{
esperar();
}
}
}.start();
CountDownTimer class help us to implement timer with custom time interval and duration. It provide 2 callback onTick(int millisUntilFinished) which called after each interval and onFinish is called when time duration is completed.
If you want to stop countdown then store instance countdown and call countdown.cancel() in onDestroy or button click(any where by user action)
You can refer this
Lets assume I have a class like that in the below. Firstly I have a CountDownTimer in a public scope but it is null now and I have a startCountDownTimer method to start my CountDownTimer, in startCountDownTimer method I set my countdowntimer but after that I want to cancel the countdowntimer when the user clicks back button but you know I created my variable in public scope and its null so when I'm trying to cancel my CountDownTimer outside of method I get NullPointerException so how can I cancel my CountDownTimer? (I dont want to create all of my CountDownTimer in public scope.)
public class test {
CountDownTimer countdowntimer;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
startCountDownTimer();
}
void startCountDowntimer(){
countdowntimer = new CountDownTimer(10000, 1) {
#Override
public void onTick(long millisUntilFinished) {
minText.setText(formatTimeMinutes(millisUntilFinished));
secondsText.setText(formatTimeSeconds(millisUntilFinished));
}
#Override
public void onFinish() {
Toast.makeText(this,"Timer Finished",Toast.LENGTH_LONG).show();
}
}.start();
}
#Override
public void onBackPressed() {
super.onBackPressed();
countdowntimer.cancel();
}
}
Try tackling this problem with boolean values.
You're getting a NullPointerException when trying to call countdowntimer.cancel() and countdowntimer isn't initialized. So let's make it so that that line of code can't be executed unless countdowntimer is initialized.
Declare a global boolean value after your countdowntimer declaration.
Boolean timerOn = false;
Now, inside your startCountdownTimer() method, right after you start the timer, set the timerOn boolean to true.
Inside your onBackPressed() method, replace your code with this:
#Override
public void onBackPressed() {
super.onBackPressed();
if (timerOn) {
countdowntimer.cancel();
timerOn = false;
}
}
This will ensure that the .cancel method is only executed when the timerOn boolean is true, which will only happen when the timer is initialized.
the program that i am making includes two different count down.
first, user has to type in the password within the time limit and press a button. If user can't input the password before the time limit, then it is over. However, if the user was able to input the password correctly before the time limit, a new timer should start.
public class MalibuCountDownTimer extends CountDownTimer
{
public MalibuCountDownTimer(long startTime, long interval)
{
super(startTime, interval);
}
#Override
public void onFinish()
{
if(hasPlanted == false) {
text.setText("Time's up!");
mTextView.setText("cya");
btnEnable(false);
startB.setEnabled(false);
}
}
#Override
public void onTick(long millisUntilFinished)
{
text.setText(""+String.format("%02d:%02d:%03d",
TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisUntilFinished)),
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)),
TimeUnit.MILLISECONDS.toMillis(millisUntilFinished) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished))
));
}
}
this is the first timer, and it is working just fine. However, i am having trouble trying to stop this timer when user entered the correct password.
I have created another class of CountDownTimer, and when the user input the correct password within the time limit, the second timer starts. I put a boolean to stop the first timer to do anything when it ends, but I have no idea how I can fully stop that counter.
if(myTimer != null) {
myTimer.cancel();
myTimer = null;
}
This is in order to cancel the timer early. First check if it is null, and if it isn't, apply the cancel method on it. Let me know if this was helpful.
:)
First you have to create service and call that service in main class where timer is running and call the onReceive method
BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Here you check the timer is running or not
timer.cancel();
}
};
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.
I have a Button in my Activity which, if not clicked within 5 seconds from creating the Activity, I want to crash the App. I tried the following but found out from logging that the OnClickListener code is executed after all other code in onCreate(Bundle) is run. So the boolean is always false when it is checked. How can I fix this?
private Boolean isClicked = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e("0-isClicked", String.valueOf(isClicked));
setContentView(R.layout.activity_main_map);
ImageView iv = (ImageView) findViewById(R.id.myBTN);
iv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(getApplicationContext(), MainActivity.class);
isClicked = true;
Log.e("1-isClicked", String.valueOf(isClicked));
startActivity(i);
}
});
Log.e("2-isClicked", String.valueOf(isClicked));
//let app crashes after 5 seconds (5000 milliseconds) if user didn't take action
if (!isClicked) {
Log.e("3-isClicked", String.valueOf(isClicked));
Thread timer = new Thread() {
public void run() {
try {
sleep(5000);
} catch (Exception e) {
e.printStackTrace();
} finally {
throw null;
}
}
};
timer.start();
}
}
And this is what LogCat gives:
E/0-isClicked﹕ false
E/2-isClicked﹕ false
E/3-isClicked﹕ false
E/1-isClicked﹕ true
I would do it the other way around: you crash your app anyway if in the 5 seconds, the user didn't click.
To ease the pain you can use CountdownTimer and do something those lines:
public void onCreate(){
new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
Log.e("isClicked", String.valueOf(isClicked));
}
public void onFinish() {
if(!isClicked) throw null;
}
}.start();
}
You can use a Timer for setting a task to be executed 5 seconds later and in that task you can finish the activity. Create the timer on onCreate()
timer = new Timer(); // Keep the timer (of type Timer) as a member of the activity class so you can access it later
timer.scheduleTask(timerTaskInstance, 5000); // timerTaskInstance is an instance of TimerTask for which you should override the run() method
Now if the button is clicked before the timer times out just cancel the timer on the button's listener method:
timer.cancel();
More info about TimerTask
I think you have to understand when oncreate is runned. Your three first log statments is from onCreate and should be:
E/0-onCreate﹕ false
E/2-onCreate﹕ false
E/3-onCreate﹕ false
See http://www.codelearn.org/android-tutorial/android-activity