Last active
July 1, 2019 11:43
-
-
Save billyjoker/36fb61a1f960ed3c0694d113d33c624f to your computer and use it in GitHub Desktop.
CountdownTimerPausable
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CountDownExtended extends CountdownTimerPausable { | |
private static final String TAG = "CountDownExtended"; | |
private static final String BAD_COUNTDOWN_LISTENER_MESSAGE = "countDownListener is null"; | |
CountDownListener countDownListener; | |
public long getMillisUntilFinished() { | |
return millisUntilFinished; | |
} | |
private long millisUntilFinished; | |
private long millisUntilFinishedPaused; | |
/*********************************************************************************************** | |
* | |
* @param startTimeSeconds segundos de inicialización de la cuenta atrás (120s = 120000ms = 2min) | |
* @param countDownListenerActivity | |
* | |
**********************************************************************************************/ | |
public CountDownExtended(long startTimeSeconds, CountDownListener countDownListenerActivity) { | |
super(startTimeSeconds * 1000L, 1000); | |
if(countDownListenerActivity != null){ | |
this.countDownListener = countDownListenerActivity; | |
} else { | |
throw new RuntimeException(BAD_COUNTDOWN_LISTENER_MESSAGE.concat(" setCountDownListener")); | |
} | |
} | |
// public void pause() { | |
// millisUntilFinishedPaused = millisUntilFinished; | |
// cancel(); | |
// } | |
// | |
// public CountDownExtended resume() { | |
// CountDownExtended countDownExtended2 = new CountDownExtended(millisUntilFinishedPaused, countDownListener); | |
// countDownExtended2.start(); | |
// return countDownExtended2; | |
// } | |
@Override | |
public void onFinish() { | |
Timber.i("millis onFinish "); | |
if(countDownListener != null){ | |
this.countDownListener.timeEnded(); | |
cancel(); | |
} else { | |
throw new RuntimeException(BAD_COUNTDOWN_LISTENER_MESSAGE.concat(" timeEnded")); | |
} | |
} | |
@Override | |
public void onTick(long millisUntilFinished) { | |
if(countDownListener == null){ | |
throw new RuntimeException(BAD_COUNTDOWN_LISTENER_MESSAGE.concat(" onTick")); | |
} | |
this.millisUntilFinished = millisUntilFinished; | |
} | |
public interface CountDownListener { | |
void timeEnded(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Schedule a countdown until a time in the future, with | |
* regular notifications on intervals along the way. | |
* | |
* Example of showing a 30 second countdown in a text field: | |
* | |
* <pre class="prettyprint"> | |
* new CountdownTimer(30000, 1000) { | |
* | |
* public void onTick(long millisUntilFinished) { | |
* mTextField.setText("seconds remaining: " + millisUntilFinished / 1000); | |
* } | |
* | |
* public void onFinish() { | |
* mTextField.setText("done!"); | |
* } | |
* }.start(); | |
* </pre> | |
* | |
* The calls to {@link #onTick(long)} are synchronized to this object so that | |
* one call to {@link #onTick(long)} won't ever occur before the previous | |
* callback is complete. This is only relevant when the implementation of | |
* {@link #onTick(long)} takes an amount of time to execute that is significant | |
* compared to the countdown interval. | |
*/ | |
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() { | |
Timber.i("CountDownTimer cancel"); | |
mHandler.removeMessages(MSG); | |
mCancelled = true; | |
} | |
/** | |
* Start the countdown. | |
*/ | |
public final synchronized CountDownTimer start() { | |
Timber.i("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() { | |
if (mPaused) { | |
return mPauseTime; | |
} else { | |
mPauseTime = mStopTimeInFuture - SystemClock.elapsedRealtime(); | |
Timber.i("CountDownTimer pause"); | |
mPaused = true; | |
mHandler.removeMessages(MSG); | |
return mPauseTime; | |
} | |
} | |
/** | |
* Resume the countdown. | |
*/ | |
public long resume() { | |
if (mPaused) { | |
mStopTimeInFuture = mPauseTime + SystemClock.elapsedRealtime(); | |
Timber.i("CountDownTimer resume"); | |
mPaused = false; | |
mHandler.sendMessage(mHandler.obtainMessage(MSG)); | |
return mPauseTime; | |
} else { | |
return mStopTimeInFuture; | |
} | |
} | |
/** | |
* 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); | |
} | |
} | |
} | |
} | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment