-
-
Save bverc/1492672 to your computer and use it in GitHub Desktop.
| /* | |
| * Copyright (C) 2008 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| package alt.android.os; | |
| import android.os.Handler; | |
| import android.os.SystemClock; | |
| import android.os.Message; | |
| /** | |
| * 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() { | |
| 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); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| }; | |
| } |
Thanks a lot! You saved my time, effort and energy.
Great Help, Thanks a lot.
It's working fine, but I'm getting this warning where you handles countdown : this handler class should be static or leaks might occur (anonymous android.os.handler)
It's working fine, but I'm getting this warning where you handles countdown : this handler class should be static or leaks might occur (anonymous android.os.handler)
try this:
// handles counting down
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@OverRide
public void handleMessage(Message msg) {
synchronized (CountDownTimerWithPause.this) {
long millisLeft = timeLeft();
if (millisLeft <= 0) {
cancel();
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 = mCountdownInterval - (SystemClock.elapsedRealtime() - lastTickStart);
// special case: user's onTick took more than mCountdownInterval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
So, is it possible to add a delay before every resume ?
So what should we do if we want to add a delay before the time starts to decrease ?
That made the trick!! Thanks a lot!!