Pause/Resume CountDownTimer Android - android

Is it possible to pause a CountDownTimer in Android? I have been looking for good solutions but I just find some ways to do this that I really don't like. As just save the left time in a variable and initialize a new CountDownTimer with that values.
That kind of solutions work but they didn't look so good because I´m using a circle Progress bar and a Textview together with my countdownTimer. Was really ugly try to look this two look good with the CountDown without be able to really "pause" it.
Here is my code for initialize the CountDownTimer with a ProgressBar and a TextView.
public void initProgress() {
if (mCountdownProgressBar == null)
mCountdownProgressBar = (CircleProgressBar) findViewById(R.id.progressBar);
mCountDownTime = 30000; //Insert your desire time in Milliseconds here
mCountdownProgressBar.setMaxProgress((int)TimeUnit.MILLISECONDS.toSeconds(mCountDownTime));
mCountDownTimer = new CustomCountDownTimer(mCountDownTime, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.v("Log_tag", "Tick of Progress" + TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished));
mCountdownProgressBar.setmProgress(TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished));
mTimer.setText(Util.getTimeForTimer(millisUntilFinished, Util.TIME_FORMAT));
}
#Override
public void onFinish() {
mCountdownProgressBar.setmProgress(0);
mTimer.setText(Util.getTimeForTimer(0, Util.TIME_FORMAT));
}
};
mCountDownTimer.start();
}
With this code you will be able to set a progressBar and a TextView together with your CountDownTimer. To be able to pause and resume it pretty easy I will post next a Custom Class for CountDownTimer.

Here is the solution!
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
public abstract class CustomCountDownTimer {
private final String TAG = "CustomCountDownTimer";
/**
* Millis since epoch when alarm should stop.
*/
private final long mMillisInFuture;
/**
* The interval in millis that the user receives callbacks
*/
private final long mCountdownInterval;
/**
* The time in millis when the timer was paused
*/
private long mTimePaused;
/**
* The final time when the timer must to stop (actual hour + countdown in millis)
*/
private long mStopTimeInFuture;
/**
* boolean representing if the timer was cancelled
*/
private boolean mCancelled = false;
/**
* boolean representing if the timer is paused
*/
private boolean mPause = 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 CustomCountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
}
/**
* Cancel the countdown.
*/
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
/**
* Pause the countdown.
*/
public synchronized final void pause() {
cancel();
//Save the time and hour to resume the timer correctly later.
mTimePaused = SystemClock.elapsedRealtime();
mPause = true;
}
/**
* Resume the countdown.
*/
public synchronized final void resume() {
//Booleans back to false value
mPause = false;
mCancelled = false;
//We set the time to a new one because the elapsedTime as change
mStopTimeInFuture = mStopTimeInFuture + (SystemClock.elapsedRealtime() - mTimePaused);
Log.d(TAG, "mStopTimeInFuture: " + mStopTimeInFuture);
mHandler.sendMessage(mHandler.obtainMessage(MSG));
}
/**
* Start the countdown.
*/
public synchronized final CustomCountDownTimer start() {
mCancelled = false;
mPause = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}
/**
* 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 (CustomCountDownTimer.this) {
if (mCancelled || mPause) {
return;
}
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
Log.d(TAG, "millisLeft: " + millisLeft);
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;
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
}

Related

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 implement coundowntimer to run beyond the limit?

i am working on a application in which i am using CountDownTimer for timer purpose which runs from the start time given to upto 0 and then receives a callback in onFinish(), but i want it to run in negative value. say, if timer is set for 1 minutes and its over then it should continue in -ve value instead of stooping the countdowntimer .
How to do that, or is there any other way to do it ?
Sorry for late answer but I hope this will helpful someone who also whats to do same as this question.
Fist android provide CountDownTimer class to perform count down timer operation. In this class timer stop while time is 0 hour, 0 minute, 0 second and onFinish() method call.
so If we want to go in minus value we need some line to comment out means in other word we have to make our custom class for count down timer. so here is custom class which can goes in minus value also. Just past it in your project and import this class instead of original CountDownTimer class.
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
public abstract class CustomCountDownTimer {
/**
* 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;
/**
* boolean representing if the timer was cancelled
*/
private boolean mCancelled = 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 CustomCountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
}
/**
* Cancel the countdown.
*/
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
/**
* Start the countdown.
*/
public synchronized final CustomCountDownTimer start() {
mCancelled = false;
//if (mMillisInFuture <= 0) {
//onFinish();
//return this;
//}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}
/**
* 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 (CustomCountDownTimer.this) {
if (mCancelled) {
return;
}
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;
sendMessageDelayed(obtainMessage(MSG), delay);
// }
}
}
};
}
important : here we remove onFinish() method from condition so it won't be finish you have to call onFinsh() method as per your requrement

Passing value of EditText to service

I have a simple Activity which creates a foreground service. I would like to pass value from EditText to Service as the amount to which the screen should be dimmed. The MainActivity looks like this:
package com.mycompany.myapp;
import android.app.*;
import android.content.*;
import android.net.*;
import android.net.wifi.*;
import android.os.*;
import android.view.*;
import android.view.View.*;
import android.widget.*;
import android.provider.*;
import android.text.*;
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final EditText edDim = (EditText) findViewById(R.id.DimVal);
edDim.setInputType(InputType.TYPE_CLASS_NUMBER);
Button btnStart =(Button) findViewById(R.id.button1);
btnStart.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
Intent intent = new Intent(getBaseContext(), MyService.class);
intent.putExtra("DimVal",edDim.getText());
startService(intent);
}
});
Button btnStop =(Button) findViewById(R.id.button2);
btnStop.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
stopService(new Intent(getBaseContext(), MyService.class));
}
});
}
}
This is the service:
package com.mycompany.myapp;
import android.app.*;
import android.content.*;
import android.net.*;
import android.os.*;
import android.provider.*;
import android.view.*;
import android.widget.*;
public class MyService extends Service
{
public int timeVal;
#Override
public IBinder onBind(Intent p1)
{
// TODO: Implement this method
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// TODO: Implement this method
Toast.makeText(this,"Usługa uruchomiona",Toast.LENGTH_LONG).show();
timeVal = intent.getIntExtra("DimVal",100);
this.registerReceiver(this.mComnReceiver,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
Notification note = new Notification(0, null,
System.currentTimeMillis());note.flags = Notification.FLAG_NO_CLEAR;
this.startForeground(1,note);
return START_STICKY;
}
/*#Override
public void onDestroy()
{
// TODO: Implement this method
super.onDestroy();
Toast.makeText(this,"Usługa zatrzymana",Toast.LENGTH_LONG).show();
}*/
private BroadcastReceiver mComnReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context p1, Intent p2)
{
ConnectivityManager manager = (ConnectivityManager)
getSystemService(CONNECTIVITY_SERVICE);
boolean isWiFi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting();
//NetworkInfo currentNetworkInfo = (NetworkInfo)
//p2.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if(isWiFi){
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, timeVal);
}else{
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 300);
}
}
};
}
But the above code does not work. Also how can I make the service check if the WiFi is on every 5 minutes? I realize that this code may not be the best solution of the problem but this is the first Android program I've written (thus the commented code).
Thank you in advance.
public void timerForWifiCheck(long intervalVal, long countVal) {
new SCBP_TimerClass(intervalVal, countVal) {
#Override
public void onTick(long tickTime) {
//Wifi checking code write here
if(SCBP_NetworkUtil.checkInternetConnection(Context)){
//Do what you wnat e.g
finish()
}else{
//Return with some error code or msg
}
}
}
#Override
public void onFinish() {
//code when the timer finshes
}
}.start();
}
For this You need to add the below two classes:
public abstract class TimerClass {
/**
* 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 SCBP_TimerClass(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 SCBP_TimerClass 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 (SCBP_TimerClass.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);
}
}
}
}
}
};
}
public class NetworkUtil {
public static boolean checkInternetConnection(Context context) {
ConnectivityManager con_manager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (con_manager.getActiveNetworkInfo() != null
&& con_manager.getActiveNetworkInfo().isAvailable()
&& con_manager.getActiveNetworkInfo().isConnected()) {
return true;
} else {
return false;
}
}
}
Hope this will help you to some extent.Cheers!
I see issue is in this line of code
intent.putExtra("DimVal",edDim.getText());
Here you should do as
intent.putExtra("DimVal",Integer.valueOf(edDim.getText().toString));
EditText getText i.e. edDim.getText() will give you Editable not the value inside. Also as you will do edDim.getText().toString will give you String value which you require to change to Integer before passing.
Note: You require to put null and check validation for edDim before passing value in intent; else it may give you runtimeerror.
Regarding the checking of WiFi it would be nice to create a broadcast receiver which receives updates for connection check and in that if connectivity is there then you can check whether it is Wifi or Mobile data and return false if mobile data. This way you do not require to check every five minutes which may lead to battery drainage.
You can check this android developer post for Determining and Monitoring the Connectivity Status.

CountdownTimer Add Time and Cancel in OnTick

I have a countdown timer and I want to add 10 seconds to it whenever my isAddTime method is true. I have successfully added it but whenever the time is added, it still finishes on the current time.
I am cancelling it in OnTick Method i tried to cancel it in other class and i successfully cancel it but i cant resume the timer.. since to cancel it in another class it will be static.
Here's my code:
timerHolder = new CountDownTimer(30000, 1000) {
#Override
public void onFinish() {
Class.isAddTime = false;
Intent i = new Intent(getBaseContext(), OtherClass.class);
startActivity(i);
}
#Override
public void onTick(long millisUntilFinished) {
timeLeft = millisUntilFinished;
if(Class.isAddTime()){
timerHolder.cancel();
AddTime();
Class.isAddTime = false;
}
timer.setText("Time left: " + String.valueOf(timeLeft / 1000));
}
}.start();
And here is the AddTime():
private void AddTime(){
timerHolder = new CountDownTimer(timeLeft + 10000, 1000) {
#Override
public void onFinish() {
Class.isAddTime = false;
Intent i = new Intent(getBaseContext(), OtherClass.class);
startActivity(i);
}
#Override
public void onTick(long millisUntilFinished) {
timeLeft += 10000;
timeLeft = millisUntilFinished;
if(Class.isAddTime()){
timerHolder.cancel();
AddTime();
Class.isAddTime = false;
}
timer.setText("Time left: " + String.valueOf(timeLeft / 1000));
}
}.start();
I was wondering why it still continue the current time even if i had it cancelled? is there other way to call cancel? is there more clean solution on how i can add time to the countdown timer?
Some people solved this problem by using custom timer. With this timer you'll be able to cancel the time inside onTick() method.
https://gist.github.com/Gautier/737759
Here is the code on Github. Hope it helps.
/*
* 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.util.Log;
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 boolean mCancelled = 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;
return this;
}
/**
* 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) {
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);
}
}
}
}
};
}
make timerHolder object null after canceling it.
if(Class.isAddTime()){
timerHolder.cancel();
timerHolder=null;
AddTime();
Class.isAddTime = false;
}

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