19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.os; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Schedule a countdown until a time in the future, with 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * regular notifications on intervals along the way. 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Example of showing a 30 second countdown in a text field: 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre class="prettyprint"> 28cf0ca99a22d65615d78f727cfb8ecf324a9b32c4Michael Chan * new CountDownTimer(30000, 1000) { 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * public void onTick(long millisUntilFinished) { 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * mTextField.setText("seconds remaining: " + millisUntilFinished / 1000); 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * public void onFinish() { 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * mTextField.setText("done!"); 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * } 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * }.start(); 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The calls to {@link #onTick(long)} are synchronized to this object so that 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * one call to {@link #onTick(long)} won't ever occur before the previous 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * callback is complete. This is only relevant when the implementation of 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onTick(long)} takes an amount of time to execute that is significant 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * compared to the countdown interval. 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class CountDownTimer { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Millis since epoch when alarm should stop. 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final long mMillisInFuture; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The interval in millis that the user receives callbacks 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final long mCountdownInterval; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mStopTimeInFuture; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param millisInFuture The number of millis in the future from the call 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to {@link #start()} until the countdown is done and {@link #onFinish()} 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is called. 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param countDownInterval The interval along the way to receive 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #onTick(long)} callbacks. 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CountDownTimer(long millisInFuture, long countDownInterval) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMillisInFuture = millisInFuture; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCountdownInterval = countDownInterval; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Cancel the countdown. 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final void cancel() { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.removeMessages(MSG); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Start the countdown. 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public synchronized final CountDownTimer start() { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMillisInFuture <= 0) { 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onFinish(); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHandler.sendMessage(mHandler.obtainMessage(MSG)); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback fired on regular interval. 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param millisUntilFinished The amount of time until finished. 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract void onTick(long millisUntilFinished); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback fired when the time is up. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public abstract void onFinish(); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG = 1; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // handles counting down 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Handler mHandler = new Handler() { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (CountDownTimer.this) { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (millisLeft <= 0) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onFinish(); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (millisLeft < mCountdownInterval) { 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no tick, just delay until done 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessageDelayed(obtainMessage(MSG), millisLeft); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long lastTickStart = SystemClock.elapsedRealtime(); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project onTick(millisLeft); 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // take into account user's onTick taking time to execute 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime(); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // special case: user's onTick took more than interval to 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // complete, skip to next interval 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (delay < 0) delay += mCountdownInterval; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendMessageDelayed(obtainMessage(MSG), delay); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 139