timer countdown 5,3,1 android - android

I have made a simple app about timer countdown. My code works perfectly, but the problem has come when I run this project.The first time my app counted normally, but the second time it counted 5,3,1 not 5,4,3,2,1
here's my code timer :
private Handler handler=new Handler();
public static int timer;
private OnTimeCompleteListener timeComplete=(OnTimeCompleteListener)this;
private Runnable timerThread=new Runnable() {
#Override
public void run() {
if(timer>0){
//Time is running
timer--;
timer_text.setText("Time : "+timer);
handler.postDelayed(this, 1000);
}else{
timeComplete.onTimeFinish();
}
}
};
public void startTimer(){
handler.postDelayed(timerThread, 100);
}
public void stopTimer(){
handler.removeCallbacks(timerThread);
}
how to make my timer work perfectly?

I thought about something like this:
private static final int TIMER_COUNTDOWN_VALUE = 5;
private Handler handler=new Handler();
private Runnable currentTimerRunnable = null;
public void startTimer() {
if( currentTimerRunnable == null ) {
currentTimerRunnable = new TimerRunnable( TIMER_COUNTDOWN_VALUE );
handler.postDelayed(currentTimerRunnable, 100);
}
}
public void stopTimer() {
if( currentTimerRunnable != null ) {
handler.removeCallbacks(currentTimerRunnable);
currentTimerRunnabel = null;
}
}
private class TimerRunnable implements Runnable {
private int timerValue;
private TimerRunnable(int startValue) {
timerValue = startValue;
#Override
public void run() {
if( timerValue > 0) {
timer--;
timerListener.onTimerUpdate( timerValue );
handler.postDelayed(this, 1000);
} else {
timerListener.onTimerFinished();
}
}
}

try this,
create CounterClass and call its start and cancle method where you want.
public class CounterClass extends CountDownTimer
{
public CounterClass(long millisInFuture, long countDownInterval)
{
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish()
{
//restart timer you wnat
//timer.start();
}
// #SuppressLint("NewApi");
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#Override
public void onTick(long millisUntilFinished)
{
long millis = millisUntilFinished;
String hms = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis)
- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis)
- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
// System.out.println(hms);
tvTime.setText(hms);
}
}
create object of CounterClass and call it's method as discribe
timer = new CounterClass(26000, 1000);//for 26 second like,26,25....1,0.
timer.start()//where you need.
timer.cancle()//where you need.

Related

Display the remaining time of the handler

I would like to know how to display the time remaining in my handler.
When I click a button, I run my handler for x seconds, and I want to display a countdown on the screen before the end of the handler.
official documentation
Example of showing a 30 second countdown in a text field:
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
Try this:
int time = 60; // seconds
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
public void run() {
time--;
mTextView.setText(time + " seconds");
}
};
handler.postDelayed(runnable, 1000);
It works fine thank you, last detail, if I put 5 seconds, it shows: 5, 4, 3, 2, 1 and 0. In the end it's 6 seconds.
Maxime, as I read in your comment to Thomas Mary's answer, you want to avoid getting an extra call to onTick().
You're seeing this because the original implementation of CountDownTimer calls onTick() for the first time as soon as (without delay) the timer is started.
How to remove the 0 at the end?
For this you can use this modified CountDownTimer :
public abstract class CountDownTimer {
private final long mMillisInFuture;
private final long mCountdownInterval;
private long mStopTimeInFuture;
private boolean mCancelled = false;
public CountDownTimer(long millisInFuture, long countDownInterval) {
mMillisInFuture = millisInFuture;
mCountdownInterval = countDownInterval;
}
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
onTick(mMillisInFuture);
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG), mCountdownInterval);
return this;
}
public abstract void onTick(long millisUntilFinished);
public abstract void onFinish();
private static final int MSG = 1;
private Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
synchronized (CountDownTimer.this) {
if (mCancelled)
return;
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
} else {
onTick(millisLeft);
sendMessageDelayed(obtainMessage(MSG), mCountdownInterval);
}
}
}
};
}
Note that you might need to adjust your implementation in onTick() method accordingly.

how to get value from countdowntimer and display into toast

i have countdown timer from 1 to 9999 if i click start button the count will start, but if click stop button i need to get current value from countdown and display that value in toast but the countdown could not stop if i click stop button please help me
private CountDownTimer countDownTimer;
private boolean timerHasStarted = false;
private Button startB;
public TextView ;
private final long startTime = 9999 * 1;
private final long interval = 1 *1 ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startB = (Button) this.findViewById(R.id.button);
startB.setOnClickListener(this);
text = (TextView) this.findViewById(R.id.timer);
countDownTimer = new MyCountDownTimer(startTime, interval);
text.setText(text.getText() + String.valueOf(startTime / 1));
}
public void onClick(View v) {
if (!timerHasStarted) {
countDownTimer.start();
timerHasStarted = true;
startB.setText("STOP");
} else {
/*countDownTimer.cancel();
timerHasStarted = false;
startB.setText("RESTART");*/
}
}
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
//text.setText("Time's up!");
countDownTimer.start();
}
#Override
public void onTick(long millisUntilFinished) {
text.setText("" + millisUntilFinished / 1);
}
}
thank you
Here is my countdown timer:
QuestionCountdownTimer
public class QuestionCountdownTimer extends CountDownTimer {
private TextView remainingTimeDisplay;
private Context context;
public QuestionCountdownTimer(Context context,long millisInFuture, long countDownInterval,TextView remainingTimeDisplay) {
super(millisInFuture, countDownInterval);
this.context = context;
this.remainingTimeDisplay = remainingTimeDisplay;
}
#Override
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
String hms = String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
remainingTimeDisplay.setText(hms);
}
#Override
public void onFinish() {
Toast.makeText(context,"COUNTDOWN FINISH :)",Toast.LENGTH_SHORT).show();
}
}
Note:
TextView remainingTimeDisplay
remainingTimeDisplay.setText(hms);
I use it to display the remaining time using a TextView
Here I call the timer:
//Start Quiz timer
QuestionCountdownTimer timer = new QuestionCountdownTimer(this,10000, 1000, remainingTimeDisplay);
timer.start();
-first parameter: this - I use it for context to show Toast message
-second parameter: 10000 - total time (10 sec)
-third parameter: 1000 - countdown interval (1 sec)
-last parameter: dispaly remaining time in real time
Tested and working
Create your CountDownTimer like this:
public class MyCountDownTimer extends CountDownTimer
{
private long timePassed = 0;
public MyCountDownTimer(long startTime, long interval)
{
super(startTime, interval);
}
#Override
public void onFinish()
{
//text.setText("Time's up!");
countDownTimer.start();
}
#Override
public void onTick(long millisUntilFinished)
{
timePassed++;
text.setText("" + millisUntilFinished / 1);
}
public long getTimePassed()
{
return timePassed;
}
}
And on your onClick just do:
((MyCoundDownTimer) countDownTimer).getTimePassed();
to retrieve the time and set your textview text to it.
You should use handler
private Handler tickResponseHandler = new Handler() {
public void handleMessage(Message msg) {
int time = msg.what;
//make toast or do what you want
}
}
and pass it to MyCountDownTimer constructor
private Handler handler;
public MyCountDownTimer(long startTime, long interval, Handler handler) {
super(startTime, interval);
this.handler = handler;
}
And send message
#Override
public void onTick(long millisUntilFinished) {
text.setText("" + millisUntilFinished / 1);
Message msg = new Message();
msg.what = millisUntilFinished/1;
handler.sendMessage(msg);
}
That's all you need to do :)

How to add and remove time on CountDownTimer?

The question is: How can I add or remove time from the CountDownTimer during the count down?
For example: The user does something good: +5sec, the user does something wrong: -5sec.
Can someone help me with some code?
Maybe something like this
abstract class MyTimer {
public MyTimer(long deadline, long interval)
{
mDeadline = deadline;
mInterval = interval;
mTimer = new MyCountDownTimer(mDeadline, mInterval);
}
public synchronized void start() {
mTimer.start();
}
public abstract void onTick(long time);
public abstract void onFinish();
public synchronized void userDidRight()
{
mTimer.cancel();
mTimer = new MyCountDownTimer(mDeadline, mInterval += 5000);
mTimer.start();
}
public synchronized void userDidWrong()
{
mTimer.cancel();
mTimer = new MyCountDownTimer(mDeadline, mInterfval -= 5000);
mTimer.start();
}
private class MyCountDownTimer extends CountDownTimer() {
private abstract void onFinish() {
MyTimer.this.onFinish();
}
private abstract void onTick(long time) {
MyTimer.this.onTick(time);
}
}
private MyCountDownTimer mTimer;
}
You could restart the timer every time the user changes:
class Timer {
private long remainingTime;
private CoundDownTimer timer;
public void addTime(long addedTimeInMillis) {
createNewTimer(remainingTime + addedTimeInMills);
}
public void createNewTimer(long timeInMillis) {
if(timer != null) {
timer.cancel();
}
timer = new CountDownTimer(timeInMillis, 1000) {
#Override
public void onTick(final long millisUntilFinished) {
remainingTime = millisUntilFinished;
}
#Override
public void onFinish() {
// do something here
}
}.start();
}
}
private class startTimer extends CountDownTimer
{
public startTimer(long millisInFuture, long countDownInterval)
{
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
currenttime=millisUntilFinished;
textview.setText("" + currenttime / 1000);
}
#Override
public void onFinish() {
textview.setText("done");
}
}
The above class is a simple derived class of CountDownTimer
CountDownTimer timer = new CountDownTimer(30000,1000);
timer.start();
long currentTime;
For example the above timer starts from 30 secs,decreases by one for each second.
To increase or decrease the timer dynamically you can cancel the old timer and initialize with your new time as shown below
timer.cancel();
timer = new CountDownTimer(currentTime+5000,1000);// +5000 to increase by 5 secs
timer.start();
you can make timer,currentTime variables as global then you can use the two different parts of code at different location.

Countdown timer with pause and resume

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

How to create an infinite loop

Ok,I need to create an infinite loop on a countdown. My code is:
public void countdown() {
if (x != null) {
x.cancel();
}
x = new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
showNotification();
}
};
x.start();
}
x is just a static countdowntimer variable. The problem is that I tried many methods to make the above code work,I mean when the countdown ends,and it displays that notification,it should start again and so on....but I can't find a way to do it.
Hope this will help you.
public void countdown(){
if (x != null) {
x.cancel();
}
x = new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
showNotification();
x.start();
}
};
}
For the record CountDownTimer(long millisInFuture, long countDownInterval)
// A not so infinite but close to infinte interval for each second
CountDownTimer cdt=new CountDownTimer(Long.MAX_VALUE, 1000) { .... }
Where Long.MAX_VALUE = 9223372036854775807 miliseconds or around 292 million of years (seconds more or less)
Its not infinite but its incredibly long.
is to restart your timer when his has finished :)
like this :
x = new CountDownTimer(20000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
showNotification();
start();// here, when your CountDownTimer has finished , we start it again :)
}
};
x.start();
Simple way to create an infinite loop:
Every one secod call method
new CountDownTimer(1000, 1000)
{
public void onTick(long l) {}
public void onFinish()
{
//Code hear
start();
}
}.start();
Why not just use a regular Timer? It will repeat on a specified interval until you call cancel(), something like:
public void countdown() {
if (x != null) {
x.cancel();
}
x = new Timer("timerName");
x.schedule(_timerTask, 0, 20000);
}
private static final TimerTask _timerTask = new TimerTask() {
#Override
public void run() {
showNotification();
}
};
You can just use a while loop:
while (true) {
// do stuff
}
When it has done "the stuff" it wil start again, infinite!
to keep your timer working just put
<countdowntime>.start();
in the onfinish block
Well, I have implemented an indefinite timer that takes multiple listeners and calls them simultaneously on a specific interval.
import android.os.CountDownTimer;
import java.util.Arrays;
public class InfiniteCounter extends CountDownTimer {
private static final int MAX_LISTENERS = 100;
private static InfiniteCounter timer;
private static InfiniteCounterListener[] listenerList = new InfiniteCounterListener[MAX_LISTENERS];
private InfiniteCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
//Milliseconds Intervals in which the counter should call its listeners
public static InfiniteCounter initInstance(int intervalMillis) {
removeAllListeners();
if (timer == null) {
timer = new InfiniteCounter(60 * 60 * 1000, intervalMillis);
timer.start();
}
return timer;
}
public static void attachListener(InfiniteCounterListener listener) {
for (int i = 0; i < MAX_LISTENERS; i++) {
if (listenerList[i] == null) {
listenerList[i] = listener;
break;
}
}
}
public static void removeListener(InfiniteCounterListener listener) {
for (int i = 0; i < MAX_LISTENERS; i++) {
if (listenerList[i] == listener) {
listenerList[i] = null;
break;
}
}
}
private static void removeAllListeners() {
Arrays.fill(listenerList, null);
}
public static void stopTimer() {
removeAllListeners();
if (timer != null) timer.cancel();
timer = null;
}
#Override
public void onTick(long l) {
for (int i = 0; i < MAX_LISTENERS; i++) {
if (listenerList[i] != null) listenerList[i].onTick();
}
}
#Override
public void onFinish() {
timer.start();
}
public interface InfiniteCounterListener {
void onTick();
}
}
Just Attach listeners to this class and with single timer, it can call multiple listeners -- which makes is very performance optimised.

Categories

Resources