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.
Related
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);
}
}
}
};
}
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.
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.
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();
}
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()