Android Countdowntimer issue - android

I have a problem with my countdowntimer.
My app has a textview saying "tap to start" then the countdown starts from 3. My problem is when I set textview visibility(View.GONE) the countdown starts from 2 if I delete the line where i set visibility the countdown works fine (starting from 3) but of course the textview remain visible
I use 750 instead of 1000 in countdown because with 1000 the countdown always starts from 2
why this happen ? How can I solve this ?
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="60sp"
android:text="Tap to start"
android:id="#+id/starttext"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
public void countdowntostart(){
TextView timetostart = (TextView) findViewById(R.id.starttext);
timetostart.setVisibility(View.GONE);
CountDownTimer countDownTimer = new CountDownTimer(3000, 750) {
TextView timestart = (TextView) findViewById(R.id.playtimetext);
public void onTick(long millisUntilFinished) {
timestart.setText("" + millisUntilFinished/1000);
}
public void onFinish() {
abcuu();
}
}.start();
}

The TextView's text display 2 is because the system have already calculated one second before it run onTick() method, therefore the 3 seconds countdown is still accurate even though the text view was displaying 2 when the countdown started. If you wish to show countdown value on a TextView, you can set the initial countdown value into TextView before the countdown.

It may be because you are not giving it a specific rounding. Try Math.ceil((double) millisecondsUntilFinished / 1000);
If that doesn't work, you might also try setting your timerstart text to "3" when you start the timer. Otherwise, I created a CustomCountdownTimer class that also has abstract methods for onStarted, onPaused, etc.
public abstract class CustomCountdownTimer {
private long millisInFuture;
private long countDownInterval;
private int secondsRemaining;
private boolean started;
private boolean paused;
public enum State {
RUNNING,
PAUSED,
STOPPED,
RESUMED,
STARTED,
FINISHED,
STATUS
}
public CustomCountdownTimer(long millisInFuture, long countDownInterval) {
this.millisInFuture = millisInFuture;
this.countDownInterval = countDownInterval;
started = false;
paused = false;
initialize();
}
public boolean isPaused(){
return paused && isStarted();
}
public boolean isStarted(){
return started;
}
public void pause() {
paused = true;
timerPaused(secondsRemaining);
}
public void resume(){
paused = false;
timerResumed(secondsRemaining);
}
public CustomCountdownTimer start() {
started = true;
return this;
}
public void stop() {
millisInFuture = 0;
}
public void initialize() {
final Handler handler = new Handler();
Log.v("status", "starting");
final Runnable counter = new Runnable(){
public void run(){
long sec = millisInFuture / 1000;
if(started && !paused) {
if(millisInFuture <= 0) {
Log.v("status", "done");
started = false;
onFinish();
} else {
Log.v("status", Long.toString(sec) + " seconds remain");
millisInFuture -= countDownInterval;
secondsRemaining = (int) Math.ceil(((double) millisInFuture / 1000));
handler.postDelayed(this, countDownInterval);
onTick(secondsRemaining);
}
} else {
Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
handler.postDelayed(this, countDownInterval);
}
}
};
handler.postDelayed(counter, countDownInterval);
}
public void updateTimer(long millisInFuture){
this.millisInFuture = millisInFuture;
}
public abstract void onTick(int secondsRemaining);
public abstract void onFinish();
public abstract void timerPaused(int secondsRemaining);
public abstract void timerResumed(int secondsRemaining);
}
Use it like this:
CustomCountdownTimer customCountdownTimer = new CustomCountdownTimer(totalSeconds * 1000, 1000) {
#Override
public void onTick(int remainingSeconds) {
// Code on each tick
}
#Override
public void onFinish() {
// Code to run when finished
}
#Override
public void timerPaused(int remainingSeconds) {
// Code to run if paused
}
#Override
public void timerResumed(int remainingSeconds) {
// Code to run when resumed from paused
}
};
customCountdownTimer.start();
Note that this is using full seconds rather than milliseconds, and it will show 3 when you start, rather than 2, because it's rounding up like I suggested earlier.

Related

Display the remaining time of the handler

I would like to know how to display the time remaining in my handler.
When I click a button, I run my handler for x seconds, and I want to display a countdown on the screen before the end of the handler.
official documentation
Example of showing a 30 second countdown in a text field:
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
Try this:
int time = 60; // seconds
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
time--;
mTextView.setText(time + " seconds");
}
};
handler.postDelayed(runnable, 1000);
It works fine thank you, last detail, if I put 5 seconds, it shows: 5, 4, 3, 2, 1 and 0. In the end it's 6 seconds.
Maxime, as I read in your comment to Thomas Mary's answer, you want to avoid getting an extra call to onTick().
You're seeing this because the original implementation of CountDownTimer calls onTick() for the first time as soon as (without delay) the timer is started.
How to remove the 0 at the end?
For this you can use this modified CountDownTimer :
public abstract class CountDownTimer {
private final long mMillisInFuture;
private final long mCountdownInterval;
private long mStopTimeInFuture;
private boolean mCancelled = false;
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
}
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
onTick(mMillisInFuture);
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG), mCountdownInterval);
return this;
}
public abstract void onTick(long millisUntilFinished);
public abstract void onFinish();
private static final int MSG = 1;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
synchronized (CountDownTimer.this) {
if (mCancelled)
return;
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
} else {
onTick(millisLeft);
sendMessageDelayed(obtainMessage(MSG), mCountdownInterval);
}
}
}
};
}
Note that you might need to adjust your implementation in onTick() method accordingly.

countdown timer in childactivity

I making an app in which i need to run Countdown timer in a Child Activity. How can i keep running timer and keep track of time when i go back to main activity(or press 'back') ?
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!isRunning){
timerTextHelper.start();
isRunning =true;
}else {
timerTextHelper.stop();
long elapsedTime = timerTextHelper.getElapsedTime();
Log.v("TAG","TIME: "+ elapsedTime/1000);
isRunning =false;
I have tried using Runnable
#Override
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
textView.setText(String.format("%d:%02d", minutes, seconds));
if (elapsedTime == -1) {
handler.postDelayed(this, 500);
}
}
public void start() {
this.startTime = System.currentTimeMillis();
this.elapsedTime = -1;
handler.post(this);
}
public void stop() {
this.elapsedTime = System.currentTimeMillis() - startTime;
handler.removeCallbacks(this);
}
public long getElapsedTime() {
return elapsedTime;
Implement the below class:
public class OtpTimer extends CountDownTimer {
/**
* #param millisInFuture The number of millis in the future from the call
* to {#link #start()} until the countdown is done and {#link #onFinish()}
* is called.
* #param countDownInterval The interval along the way to receive
* {#link #onTick(long)} callbacks.
*/
private OtpTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
private static OtpTimer otpTimer;
private static TextView otp_text;
private static long sec,min;
/**
*
* #param millisInFuture total time of timer
* #param countDownInterval callback time of {#link #onTick(long)}
* #param textView instace of textview to show time in text view
*/
public static synchronized void getInstance(long millisInFuture, long countDownInterval, TextView textView)
{
if(otpTimer==null) {
otpTimer = new OtpTimer(millisInFuture, countDownInterval);
otpTimer.start();
}
otp_text=textView;
if(min>=1 && sec>=10)
otp_text.setText("0"+String.valueOf(min)+":"+String.valueOf(sec));
else if(min>=1 && sec<=10)
{
otp_text.setText("0"+String.valueOf(min)+":"+"0"+String.valueOf(sec));
}
else if(sec>=10)
otp_text.setText("00"+":"+String.valueOf(sec));
else if(sec==0)
otp_text.setText("Start again");
else
otp_text.setText("00"+":"+"0"+String.valueOf(sec));
}
#Override
public void onTick(long millisUntilFinished) {
sec=millisUntilFinished/1000;
min=sec/60;
sec=sec%60;
if(min>=1 && sec>=10)
otp_text.setText("0"+String.valueOf(min)+":"+String.valueOf(sec));
else if(min>=1 && sec<=10)
{
otp_text.setText("0"+String.valueOf(min)+":"+"0"+String.valueOf(sec));
}
else if(sec>=10)
otp_text.setText("00"+":"+String.valueOf(sec));
else
otp_text.setText("00"+":"+"0"+String.valueOf(sec));
}
#Override
public void onFinish() {
sec=0;
otp_text.setText("Start again");
}
public static void Restart(long millisInFuture, long countDownInterval, TextView textView,Boolean voice,Boolean contact){
if(otpTimer!=null)
{
otpTimer.cancel();
otpTimer=null;
}
getInstance(millisInFuture, countDownInterval,textView,voice,contact);
}
public static void setNull()
{
if(otpTimer!=null)
{
otpTimer.cancel();
otpTimer=null;
}
}}
Now to start the timer, simply call the below line in the onCreate and onResume :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
OtpTimer.getInstance(30000,1000,m_otp_timer);
}
#Override
protected void onResume() {
invalidateOptionsMenu();
super.onResume();
OtpTimer.getInstance(30000,1000,m_otp_timer);
}
Here 30sec timer and count will increase by 1sec and m_otp_timer is the textview which will display the count.
And to restart the timer simply call:
OtpTimer.Restart(30000, 1000, m_otp_timer);
create a broadCastReceiver and register it to your manifest
<receiver
android:name=".receivers.TimerReceiver">
<intent-filter>
<action android:name="YOUR.PACKAGE.NAME.action.RECEIVER_TIMER" />
</intent-filter>
</receiver>
the action is used to send intent to only your receiver
and create a class for your Receiver
class TimerReceiver : BroadcastReceiver(val callback:Callback) {
override fun onReceive(context: Context?, data: Intent?) {
callback.onNewTime(data.getIntExtra("min",0),data.getIntExtra("sec",0))
}
interface Callback {
fun onNewTime(int min,int sec)
}
}
then in your activity's body create an instance of your receiver
TimerReceiver receiver;
then in your activity's onCreate() make your object
receiver = TimerReceiver(this)
then in your activity's onStart register your receiver
registerReceiver(receiver,IntentFilter("YOUR.PACKAGE.NAME.acrion.RECEIVER_TIMER"))
and in your activity's onStop unregister your receiver
unregisterReceiver(receiver)
and at the end implement the TimerReceiver.Callback methods in your activity
override fun onNewTime(min:Int,sec:Int){
textView.setText(String.format("%d:%02d", min, sec));
}
so you are ready and in your TimeTask when you want to update timer sendBroadCast and put min and sec into intent.

How to add and remove time on CountDownTimer?

The question is: How can I add or remove time from the CountDownTimer during the count down?
For example: The user does something good: +5sec, the user does something wrong: -5sec.
Can someone help me with some code?
Maybe something like this
abstract class MyTimer {
public MyTimer(long deadline, long interval)
{
mDeadline = deadline;
mInterval = interval;
mTimer = new MyCountDownTimer(mDeadline, mInterval);
}
public synchronized void start() {
mTimer.start();
}
public abstract void onTick(long time);
public abstract void onFinish();
public synchronized void userDidRight()
{
mTimer.cancel();
mTimer = new MyCountDownTimer(mDeadline, mInterval += 5000);
mTimer.start();
}
public synchronized void userDidWrong()
{
mTimer.cancel();
mTimer = new MyCountDownTimer(mDeadline, mInterfval -= 5000);
mTimer.start();
}
private class MyCountDownTimer extends CountDownTimer() {
private abstract void onFinish() {
MyTimer.this.onFinish();
}
private abstract void onTick(long time) {
MyTimer.this.onTick(time);
}
}
private MyCountDownTimer mTimer;
}
You could restart the timer every time the user changes:
class Timer {
private long remainingTime;
private CoundDownTimer timer;
public void addTime(long addedTimeInMillis) {
createNewTimer(remainingTime + addedTimeInMills);
}
public void createNewTimer(long timeInMillis) {
if(timer != null) {
timer.cancel();
}
timer = new CountDownTimer(timeInMillis, 1000) {
#Override
public void onTick(final long millisUntilFinished) {
remainingTime = millisUntilFinished;
}
#Override
public void onFinish() {
// do something here
}
}.start();
}
}
private class startTimer extends CountDownTimer
{
public startTimer(long millisInFuture, long countDownInterval)
{
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
currenttime=millisUntilFinished;
textview.setText("" + currenttime / 1000);
}
#Override
public void onFinish() {
textview.setText("done");
}
}
The above class is a simple derived class of CountDownTimer
CountDownTimer timer = new CountDownTimer(30000,1000);
timer.start();
long currentTime;
For example the above timer starts from 30 secs,decreases by one for each second.
To increase or decrease the timer dynamically you can cancel the old timer and initialize with your new time as shown below
timer.cancel();
timer = new CountDownTimer(currentTime+5000,1000);// +5000 to increase by 5 secs
timer.start();
you can make timer,currentTime variables as global then you can use the two different parts of code at different location.

Countdown timer with pause and resume

I want to do countdown timer with pause and restart.Now i am displaying countdown timer By implenting ontick() and onfinish().please help me out.HEre is th code for countdown timer
final CountDownTimer Counter1 = new CountDownTimer(timervalue1 , 1000)
{
public void onTick(long millisUntilFinished)
{
System.out.println("onTick method!"(String.valueOf(millisUntilFinished/1000)));long s1=millisUntilFinished;
}
public void onFinish()
{
System.out.println("Finished!");
}
}
in onTick method..save the milliseconds left
long s1=millisUntilFinished;
when you want to pause the timer use..
Counter.cancel();
when you want to resume create a new countdowntimer with left milliseconds..
timervalue=s1
counter= new Counter1();
counter.start();
See this link
I would add something to the onTick handler to save the progress of the timer in your class (number of milliseconds left).
In the onPause() method for the activity call cancel() on the timer.
In the onResume() method for the activity create a new timer with the saved number of milliseconds left.
Refer the below links
LINK
LINK
My first answer on stackOverFlow, hope it should help :) ...
This is how I solved the problem, control timer from Fragment, Bottomsheet, Service, Dialog as per your requirement, keep a static boolean variable to control.
declare in your Activity:
long presetTime, runningTime;
Handler mHandler =new Handler();
Runnable countDownRunnable;
Toast toastObj;
public static boolean shouldTimerRun = true;
TextView counterTv;
In onCreate:
presetTime =60000L;
runningTime= presetTime;
//setting up Timer
countDownRunnable=new Runnable() {
#Override
public void run() {
if (shouldTimerRun) //if false, it runs but skips counting
{
counterTv.setText(simplifyTimeInMillis(runningTime));
if (runningTime==0) {
deployToast("Task Completed"); //show toast on task completion
}
runningTime -= 1000;
presetTime = runningTime; //to resume the timer from last position
}
mHandler.postDelayed(countDownRunnable,1000); //simulating on-tick
}
};
mHandler.post(countDownRunnable); // Start our CountdownTimer
Now, whenever you want to pause the timer change the value of shouldTimerRun false and to resume make it true.
#Override
public void onResume() {
super.onResume();
shouldTimerRun=true;
}
#Override
public void onPause() {
super.onPause();
shouldTimerRun=false;
deployToast("Timer is paused !!");
}
Helping methods: (can be skipped)
public static String simplifyTimeInMillis(long time) {
String result="";
long difference = time;
long secondsInMilli = 1000;
long minutesInMilli = secondsInMilli * 60;
long hoursInMilli = minutesInMilli * 60;
if (difference<1000){
return "0";
}
if (difference>=3600000) {
result = result + String.valueOf(difference / hoursInMilli) + "hr ";
difference = difference % hoursInMilli;
}
if (difference>=60000) {
result = result + String.valueOf(difference / minutesInMilli) + "m ";
difference = difference % minutesInMilli;
}
if (difference>=1000){
result = result + String.valueOf(difference / secondsInMilli) + "s";
}
return result;
}
public void deployToast(String msg){
if (toastObj!=null)
toastObj.cancel();
toastObj = Toast.makeText(mContext,msg,Toast.LENGTH_SHORT);
toastObj.show();
}
I'm using two private vars in this case:
private long startPauseTime;
private long pauseTime = 0L;
public void pause() {
startPauseTime = System.currentTimeMillis();
}
public void resumen(){
pauseTime += System.currentTimeMillis() - startPauseTime;
}
I am afraid that it is not possible to pause or stop CountDownTimer and pausing or stopping in onTick has no effect whatsoever user TimerTask instead.
Set up the TimerTask
class UpdateTimeTask extends TimerTask {
public void run() {
long millis = System.currentTimeMillis() - startTime;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
timeLabel.setText(String.format("%d:%02d", minutes, seconds));
}
}
if(startTime == 0L) {
startTime = evt.getWhen();
timer = new Timer();
timer.schedule(new UpdateTimeTask(), 100, 200);
}
You can add event listener's like this..
private Handler mHandler = new Handler();
...
OnClickListener mStartListener = new OnClickListener() {
public void onClick(View v) {
if (mStartTime == 0L) {
mStartTime = System.currentTimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 100);
}
}
};
OnClickListener mStopListener = new OnClickListener() {
public void onClick(View v) {
mHandler.removeCallbacks(mUpdateTimeTask);
}
};
For more refer to Android Documentation.
//This timer will show min:sec format and can be paused and resumed
public class YourClass extends Activity{
TextView timer;
CountDownTimer ct;
long c = 150000; // 2min:30sec Timer
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.YourXmlLayout);
timer = (TextView)findViewById(R.id.Yourtimer)
startTimer(); // it will start the timer
}
public void startTimer(){
ct = new CountDownTimer(c,1000) {
#Override
public void onTick(long millisUntilFinished) {
// Code to show the timer in min:sec form
// Here timer is a TextView so
timer.setText(""+String.format("%02d:%02d",millisUntilFinished/60000,(millisUntilFinished/1000)%60));
c = millisUntilFinished; // it will store millisLeft
}
#Override
public void onFinish() {
//your code here
}
};
ct.start();
}
/*===========================================================
*after creating this you can pause this by typing ct.cancel()
*and resume by typing startTimer()*/
public class MainActivity extends AppCompatActivity {
TextView textView;
CountDownTimer ctimer;
boolean runCountDown;
private long leftTime;
private static final long MILL_IN_FUTURE = 6000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text_view);
textView.setText("Click to start");
textView.setOnClickListener(this::clickStartAndPauseAndResume);
leftTime = MILL_IN_FUTURE;
}
public void clickStartAndPauseAndResume(View view) {
if (!runCountDown) {
long time = (leftTime == 0 || leftTime == MILL_IN_FUTURE) ? MILL_IN_FUTURE : leftTime;
ctimer = new CountDownTimer(time, 1) {
#Override
public void onTick(long l) {
leftTime = l;
textView.setText(l + "ms");
}
#Override
public void onFinish() {
textView.setText("Done");
leftTime = 0;
runCountDown = false;
textView.postDelayed(new Runnable() {
#Override
public void run() {
textView.setText("Click to start");
}
}, 1000);
}
}.start();
runCountDown = true;
} else {
ctimer.cancel();
textView.setText(textView.getText() + "\n Click to resume");
runCountDown = false;
}
}
}
A nice and simple way to create a Pause/Resume for your CountDownTimer is to create a separate method for your timer start, pause and resume as follows:
public void timerStart(long timeLengthMilli) {
timer = new CountDownTimer(timeLengthMilli, 1000) {
#Override
public void onTick(long milliTillFinish) {
milliLeft=milliTillFinish;
min = (milliTillFinish/(1000*60));
sec = ((milliTillFinish/1000)-min*60);
clock.setText(Long.toString(min)+":"+Long.toString(sec));
Log.i("Tick", "Tock");
}
The timerStart has a long parameter as it will be reused by the resume() method below. Remember to store your milliTillFinished (above as milliLeft) so that you may send it through in your resume() method. Pause and resume methods below respectively:
public void timerPause() {
timer.cancel();
}
private void timerResume() {
Log.i("min", Long.toString(min));
Log.i("Sec", Long.toString(sec));
timerStart(milliLeft);
}
Here is the code for the button FYI:
startPause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(startPause.getText().equals("Start")){
Log.i("Started", startPause.getText().toString());
startPause.setText("Pause");
timerStart(15*1000);
} else if (startPause.getText().equals("Pause")){
Log.i("Paused", startPause.getText().toString());
startPause.setText("Resume");
timerPause();
} else if (startPause.getText().equals("Resume")){
startPause.setText("Pause");
timerResume();
}

Pause CountDownTimer in Android when activity is not in front

I have an activity that uses a CountDownTimer that counts down from 10. How do I pause that timer when the activity is no longer in focus, like if the user get a call or something, then resume the timer when the user goes back to the activity? Is this even possible?
I would add something to the onTick handler to save the progress of the timer in your class (number of milliseconds left).
In the onPause() method for the activity call cancel() on the timer.
In the onResume() method for the activity create a new timer with the saved number of milliseconds left.
You can use pause() to pause the timer and later on Start or Resume the countDownTimer by calling start().
/**
* This class uses the native CountDownTimer to
* create a timer which could be paused and then
* started again from the previous point. You can
* provide implementation for onTick() and onFinish()
* then use it in your projects.
*/
public abstract class CountDownTimerPausable {
long millisInFuture = 0;
long countDownInterval = 0;
long millisRemaining = 0;
CountDownTimer countDownTimer = null;
boolean isPaused = true;
public CountDownTimerPausable(long millisInFuture, long countDownInterval) {
super();
this.millisInFuture = millisInFuture;
this.countDownInterval = countDownInterval;
this.millisRemaining = this.millisInFuture;
}
private void createCountDownTimer(){
countDownTimer = new CountDownTimer(millisRemaining,countDownInterval) {
#Override
public void onTick(long millisUntilFinished) {
millisRemaining = millisUntilFinished;
CountDownTimerPausable.this.onTick(millisUntilFinished);
}
#Override
public void onFinish() {
CountDownTimerPausable.this.onFinish();
}
};
}
/**
* Callback fired on regular interval.
*
* #param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished);
/**
* Callback fired when the time is up.
*/
public abstract void onFinish();
/**
* Cancel the countdown.
*/
public final void cancel(){
if(countDownTimer!=null){
countDownTimer.cancel();
}
this.millisRemaining = 0;
}
/**
* Start or Resume the countdown.
* #return CountDownTimerPausable current instance
*/
public synchronized final CountDownTimerPausable start(){
if(isPaused){
createCountDownTimer();
countDownTimer.start();
isPaused = false;
}
return this;
}
/**
* Pauses the CountDownTimerPausable, so it could be resumed(start)
* later from the same point where it was paused.
*/
public void pause()throws IllegalStateException{
if(isPaused==false){
countDownTimer.cancel();
} else{
throw new IllegalStateException("CountDownTimerPausable is already in pause state, start counter before pausing it.");
}
isPaused = true;
}
public boolean isPaused() {
return isPaused;
}
}
No need to create a new Timer, just set the millisUntilFinished = total. For instance
private CountDownTimer cdTimer;
private long total = 30000;
...
toggleButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view){
if(toggleButton.isChecked()) {
startCountDownTimer();
}else{
cdTimer.cancel();
}
}
});
...
private void startCountDownTimer() {
cdTimer = new CountDownTimer(total, 1000) {
public void onTick(long millisUntilFinished) {
//update total with the remaining time left
total = millisUntilFinished;
nTimeLabel.setText("seconds remaining: " + millisUntilFinished/ 1000);
}
public void onFinish() {
nTimeLabel.setText("done!");
}
}.start();
}
This must be exactly what you're looking for. Source is this Gist.
package alt.android.os;
import android.os.Handler;
import android.os.SystemClock;
import android.os.Message;
public abstract class CountDownTimer {
/**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture;
/**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval;
private long mStopTimeInFuture;
private long mPauseTime;
private boolean mCancelled = false;
private boolean mPaused = false;
/**
* #param millisInFuture The number of millis in the future from the call
* to {#link #start()} until the countdown is done and {#link #onFinish()}
* is called.
* #param countDownInterval The interval along the way to receive
* {#link #onTick(long)} callbacks.
*/
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
}
/**
* Cancel the countdown.
*
* Do not call it from inside CountDownTimer threads
*/
public final void cancel() {
mHandler.removeMessages(MSG);
mCancelled = true;
}
/**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
mCancelled = false;
mPaused = false;
return this;
}
/**
* Pause the countdown.
*/
public long pause() {
mPauseTime = mStopTimeInFuture - SystemClock.elapsedRealtime();
mPaused = true;
return mPauseTime;
}
/**
* Resume the countdown.
*/
public long resume() {
mStopTimeInFuture = mPauseTime + SystemClock.elapsedRealtime();
mPaused = false;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return mPauseTime;
}
/**
* Callback fired on regular interval.
* #param millisUntilFinished The amount of time until finished.
*/
public abstract void onTick(long millisUntilFinished);
/**
* Callback fired when the time is up.
*/
public abstract void onFinish();
private static final int MSG = 1;
// handles counting down
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
synchronized (CountDownTimer.this) {
if (!mPaused) {
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
} else if (millisLeft < mCountdownInterval) {
// no tick, just delay until done
sendMessageDelayed(obtainMessage(MSG), millisLeft);
} else {
long lastTickStart = SystemClock.elapsedRealtime();
onTick(millisLeft);
// take into account user's onTick taking time to execute
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
// special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval;
if (!mCancelled) {
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
}
}
};
}
You can try using Hourglass
Hourglass hourglass = new Hourglass(50000, 1000) {
#Override
public void onTimerTick(long timeRemaining) {
// Update UI
Toast.show(MainActivity.this, String.valueOf(timeRemaining), Toast.LENGTH_SHORT).show();
}
#Override
public void onTimerFinish() {
// Timer finished
Toast.show(MainActivity.this, "Timer finished", Toast.LENGTH_SHORT).show();
}
};
Use hourglass.startTimer(); to start the timer.
It has helper methods which allow to pause and resume the timer.
hourglass.pauseTimer();
AND
hourglass.resumeTimer();
Here is the code below .Use it in your activities it works fine.
public class MainActivity extends AppCompatActivity {
TextView textview;
final static long INTERVAL = 1000;
final static long TIMEOUT = 11000;
static long millisecondsleft;
boolean isPause =false;
CountDownTimer countDownTimer;
CountDownTimer countDownTimeronResume;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview=findViewById(R.id.textviewcheck);
}
#Override
protected void onResume() {
super.onResume();
if(isPause == false) {
countDownTimer = new CountDownTimer(TIMEOUT, INTERVAL) {
#Override
public void onTick(long millisUntilFinished) {
millisecondsleft = millisUntilFinished;
textview.setText(":" + String.format("%02d", millisUntilFinished / 1000));
}
#Override
public void onFinish() {
textview.setText("DONE!");
}
}.start();
} else{
countDownTimeronResume = new CountDownTimer(millisecondsleft, INTERVAL) {
#Override
public void onTick(long millisUntilFinished) {
Toast.makeText(MainActivity.this, "ONPAUSED", Toast.LENGTH_SHORT).show();
millisecondsleft = millisUntilFinished;
textview.setText(":" + String.format("%02d", millisUntilFinished / 1000));
}
#Override
public void onFinish() {
textview.setText("DONE!");
}
}.start();
}
}
#Override
protected void onPause() {
super.onPause();
if(countDownTimer!=null){
countDownTimer.cancel();
isPause = true;
}
if(countDownTimeronResume!=null){
countDownTimeronResume.cancel();
}
}
}
For Kotlin user, checkout this
For eg:
// Init timer
lateinit var timerExt: CountDownTimerExt
timerExt = object : CountDownTimerExt(TIMER_DURATION, TIMER_INTERVAL) {
override fun onTimerTick(millisUntilFinished: Long) {
Log.d("MainActivity", "onTimerTick $millisUntilFinished")
}
override fun onTimerFinish() {
Log.d("MainActivity", "onTimerFinish")
}
}
// Start/Resume timer
timerExt.start()
// Pause timer
timerExt.pause()
// Restart timer
timerExt.restart()

Categories

Resources