I have a CountDown timer that counts down from 10000ms to 0ms in increments of 1 second each to make a button clickable after 10 seconds. Although the timer is accurate and does what the code says, I would like to change the way the seconds are expressed but I don't know how.
java:
void startTimer() {
cTimer = new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
c.setText("Please wait " + millisUntilFinished/1000 + " seconds");
thx.setText(millisUntilFinished/1000 + "");
thx.setAlpha(.5f);
thx.setClickable(false);
}
public void onFinish() {
c.setText("done");
thx.setText("ready");
thx.setAlpha(1f);
thx.setClickable(true);
}
};
cTimer.start();
}
Outputted (Every second): 9, 8, 7, 6, 5, 4, 3, 2, 1, (still 1), ready
Desired: (Every second): 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, ready
Thanks,
B
EDIT:
I added 1 to the countdown, thx.setText(((millisUntilFinished/1000) + 1) + "");
New output: 10, 9, 8, 7, 6, 5, 4 ,3 , 2, (Still 2), ready
Closer... but not quite.
This is just my investigation on CountDownTimer when I used CountDownTimer
few month before and its work fine in my application.
public void onTick(long millisUntilFinished)
This millisUntilFinished will give the remaining time in millisecond, and last 1000 millisecond is to call onFinish() method, So onTick method will get called until the remaining time is more than (1000(for OnFinish) + 1000(for counter)) milliseconds, if the last remaining millisecond is less than 2000millisecond it will skip the onTick() and it will directly call onFinish() when timer ends. For more details just see Handler method in this source.
So the main problem is when we give some X(our case 10000)milliseconds, but to start the counter it's taking some 50 to 150 milliseconds, So if we add that millisecond in our total time we will get the counter until end,
So you can try like this, Nothing change just I added 150 milliseconds in your total time.
void startTimer() {
cTimer = new CountDownTimer(10150, 1000) {
public void onTick(long millisUntilFinished) {
c.setText("Please wait " + millisUntilFinished/1000 + " seconds");
thx.setText(millisUntilFinished/1000 + "");
thx.setAlpha(.5f);
thx.setClickable(false);
}
public void onFinish() {
c.setText("done");
thx.setText("ready");
thx.setAlpha(1f);
thx.setClickable(true);
}
};
cTimer.start();
}
Let me know if its works or not, If you ask me why you are not using Handler, I can say CountDownTime internally using Handler.
Try this one for counter:
public void CountDown() {
final TextView textic = (TextView) findViewById(R.id.tvConuter);
CountDownTimer Count = new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
long str = millisUntilFinished / 1000;
String TimeFinished = String.valueOf(str);
textic.setText(TimeFinished);
}
public void onFinish() {
textic.setText("STOP");
}
};
Count.start();
}
This worked perfectly for me.
I would suggest to use Timer() or Handler() class.
int tick = 0;
Handler handler = new Handler();
Runnable r = new Runnable() {void run(){
if (i < 10) {
handler.postDelayed()}
else {
//finished
tick = 0;
}}};
starting:
handler.post(r);
new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds: " + millisUntilFinished / 1000);
//here you can have your logic to set text to edittext
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
private void countDownTimer(int seconds) {
countDownTimer = new CountDownTimer(seconds * 1000L, 1000 - 500) {
public void onTick(long millisUntilFinished) {
//Convert to seconds
int secondsUnillFinished = (int) (millisUntilFinished / 1000);
//Set text to seconds
textView.setText(String.valueOf(secondsUnillFinished));
//At zero, do something
if(secondsUnillFinished == 0) {
countDownTimer.cancel();
textView.setVisibility(View.INVISIBLE);
}
}
#SuppressLint("SetTextI18n")
public void onFinish() {
//Dont put anything here
}
}.start();
}
Related
I am beginner in android.
What I want:
Here I am trying to achieve that sub handler should call 10 times of every second of main handler. And that main handler should continue until 20 seconds.
Issue:
To check that i\I have used log but its not working. It goes into sub handler some times 8 times or some times 9 or 10.
Is there any logical error or is there any other better way to achieve this?
Thank you.
My code:
int i=0;
int cont;
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
i++;
cont = 1;
Log.e("main count", i + "");
final Handler handler1 = new Handler();
handler1.postDelayed(new Runnable() {
#Override
public void run() {
if (cont <= 10) {
Log.e("sub count ", cont + "");
cont++;
handler1.postDelayed(this, 100);
}
}
}, 100);
if (!(i == 20)) {
handler.postDelayed(this, 1000);
}
}
}, 1000);
It's difficult to execute code with precise timing using a Handler because you have to measure the time yourself.
It's much easier to use the built-in classes like ScheduledThreadPoolExecutor or Timer. I'd recommend the first as it would require less changes to the code. You should pick one of the scheduleAtFixedRate() or scheduleWithFixedDelay() methods according to your requirements.
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
final ScheduledFuture mainFuture = executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
if (i < 20) {
Log.e("main count ", i + "");
i++;
} else {
mainFuture.cancel(true);// stop after 20 executions
}
},
0, /*initial wait time*/
1, /* time between consecutive runs */
TimeUnit.SECONDS);
final ScheduledFuture subFuture = executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
if (cont < 20 * 10) {
Log.e("sub count ", cont + "");
cont++;
} else {
subFuture.cancel(true);// stop after 200 executions
executor.shutdown();
}
},
100, /*adjust this according to the desired sequencing of the count tasks */
100, /* time between consecutive runs */
TimeUnit.MILLISECONDS);
You could also use a single ScheduledFuture and execute the code for main count after every 10 executions of the sub count code.
I have made a Countdown to a future date (with remaining days, hours, minutes, seconds) using CountDownTimer and lots of code from this answer: https://stackoverflow.com/a/32773716/3984944
Now I want to do exactly the same but counting up from a past date. My TextView should refresh every second and show the elapsed time.
What I tried:
I tried manipulating the CountDownTimer so that it works in reverse order. Changing the interval to -1000 or adding 2000 milliseconds to the Countdown every second. Both didn't work.
Then I figured I should use the Chronometer class. The standard Chronometer only displays hours, minutes and seconds as far as I'm concerned. So no days. I then wrote the following code in the style of the CountDownTimer answer I found before that updates a TextView with the desired data:
final Chronometer ch = (Chronometer) findViewById(R.id.ch_chronometer);
final TextView tv = (TextView) findViewById(R.id.tv_show_stopwatch);
ch.setBase(endMillis); //endMillis is the date in Milliseconds
chCountdownSince.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
public void onChronometerTick(Chronometer cArg) {
long t = System.currentTimeMillis() - chCountdownSince.getBase();
long days = TimeUnit.MILLISECONDS.toDays(t);
t -= TimeUnit.DAYS.toMillis(days);
long hours = TimeUnit.MILLISECONDS.toHours(t);
t -= TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(t);
t -= TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(t);
String stopwatchDisplay = "Days: %d Hours: %d Minutes: %d Seconds: %d";
stopwatchDisplay = String.format(stopwatchDisplay, days, hours, minutes, seconds);
tv.setText(stopwatchDisplay);
}
});
I feel like this snipped makes absolute sense but upon execution it doesn't change my TextView at all. I feel like this is just not how Chronometer works but I don't know what I'm doing wrong.
Edit :
I think you forgot to start Chronometer completely.
Given that
The calls to onTick(long) are synchronized to this object so that one
call to onTick(long) won't ever occur before the previous callback is
complete.
Its unlikely that ticks are done on UI thread, but this is exactly where you need to set your text, try changing
tv.setText(stopwatchDisplay);
to
tv.post(new Runnable() {
public void run() {
tv.setText(stopwatchDisplay);
});
please use handler..
public void countDownStart() {
handler = new Handler();
runnable = new Runnable(){
#Override
public void run(){
handler.postDelayed(this,1000);
try {
FestCountdownTimer timer = new FestCountdownTimer(00, 00, 9, 3, 01, 2017);
new CountDownTimer(timer.getIntervalMillis(), 1000) {
#Override
public void onTick(long millisUntilFinished){
int days = (int) ((millisUntilFinished / 1000) / 86400);
int hours = (int) (((millisUntilFinished / 1000)
- (days * 86400)) / 3600);
int minutes = (int) (((millisUntilFinished / 1000)
- (days * 86400) - (hours * 3600)) / 60);
int seconds = (int) ((millisUntilFinished / 1000) % 60);
String countdown = String.format("%02dd %02dh %02dm %02ds", days,
hours, minutes, seconds);
txtTimerDay.setText("" + String.format("%02d", days));
txtTimerHour.setText("" + String.format("%02d", hours));
txtTimerMinute.setText(""
+ String.format("%02d", minutes));
txtTimerSecond.setText(""
+ String.format("%02d", seconds));
}
#Override
public void onFinish() {
textViewGone();
MainActivity.aSwitch.setChecked(false);
creditText.setText("Toggle On To Start");
}
}.start();
} catch (Exception e) {
e.printStackTrace(); }
}
};
handler.postDelayed(runnable, 1 * 1000);
}
Remember, 9 is Hours,3 is date,1 is Febraury Month..Month starts from 0th Index
FestCountdownTimer class
public class FestCountdownTimer {
private long intervalMillis;
public FestCountdownTimer(int second, int minute, int hour, int monthDay, int month, int year) {
Time futureTime = new Time();
// Set date to future time
futureTime.set(second, minute, hour, monthDay, month, year);
futureTime.normalize(true);
long futureMillis = futureTime.toMillis(true);
Time timeNow = new Time();
// Set date to current time
timeNow.setToNow();
timeNow.normalize(true);
long nowMillis = timeNow.toMillis(true);
// Subtract current milliseconds time from future milliseconds time to retrieve interval
intervalMillis = futureMillis - nowMillis;
}
public long getIntervalMillis() {
return intervalMillis;
}
}
Hope it helps.. :)
For my code I use a countdown timer, however I add seconds to it as after they get an answer correct, the timer is reset to 5 seconds. The problem with this is that the text that displays the time still has the wrong number, it doesn't repeat digits. For instance if it was a 5 second timer and it goes 5,4,3 then the user gets it right, the time will go 3, 3, 3, 2, 1.
Here is my countdown code
n = 5000;
time = new TextView(this);
time.setTextColor(Color.parseColor("#FFFFFF"));
timer = new CountDownTimer(n, 1000) {
public void onTick(long millisUntilFinished) {
time.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
Intent endIntent = new Intent(MainActivity.this, Endgame.class);
endIntent.putExtra("rounds",round);
MainActivity.this.startActivity(endIntent);
}
}.start();
Then if the user gets the question right - this is the part that restarts it
if(person == false){
picturechanger();
n=5000;
timer.onTick(5000);
}
Try:
if(person == false){
picturechanger();
n=5000; // Not sure why u put n=5000 here..?
if(timer != null)
timer.cancel();
timer.start();
}
I have the following CountDownTimer that helps me to set a button visible every 490 ms 30 seconds long.
Is it possible to say that the first 10 seconds the "tick" should be for example 1000ms, the next 10 seconds 700 ms and the last 10 seconds 490ms ?
new CountDownTimer(30000, 490) {
#Override
public void onTick(long millisUntilFinished) {
for(int i = 0; i< arr.size(); i++){
Button aga = arr.get(i);
if(aga.getVisibility() == View.VISIBLE){
aga.setVisibility(View.GONE);
}
}
int zufall = (int) (Math.random()*23);
setNextButton(arr.get(zufall));
}
Hope this will helpful.
public void countDown(long time) {
if (time == 490) {
return;
}
new CountDownTimer(10000, time) {
public void onTick(long millisUntilFinished) {
// Do whatever you want
}
public void onFinish() {
countDown(nextTime); // nextTime can be 700, 100, ... It's up to you. (Your rule). :">
}
}.start();
}
Aside from launching new timers at those intervals to handle the new requirement, your best bet would just be to find a common divisor and set that as your interval, then use a switch with modulus to act at your desired times.
Timer mTimer; // Global
public void countDownTimerCaller()
{
static int count = 0;
int time;
switch(count)
{
case 0:
time = 1000;
break;
case 1:
time = 700;
break;
case 2:
time = 490;
break;
default:
mTimer.cancel(); // stop timer
return;
}
new CountDownTimer(10000, time) {
#Override
public void onTick(long millisUntilFinished) {
for(int i = 0; i< arr.size(); i++){
Button aga = arr.get(i);
if(aga.getVisibility() == View.VISIBLE){
aga.setVisibility(View.GONE);
}
}
int zufall = (int) (Math.random()*23);
setNextButton(arr.get(zufall));
}
}
count++;
}
mTimer = new Timer().schedule(countDownTimerCaller, 10000); // call from where ever you created CountDownTimer instance
Trying to make a small countdown timer in my app but it's not working.
Idea is to count down to a specific time. First by days and when it gets closer, by hours.
The following method is inside my Fragmentclass.java (so it's a fragment)
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
Calendar cal = Calendar.getInstance();
cal.set(2012, 8, 29, 10, 0);
long endTime = cal.getTimeInMillis();
long currentTime = System.currentTimeMillis();
long remaining = currentTime - endTime;
long seconds = remaining / 1000 % 60;
new CountDownTimer(seconds, 1000) {
TextView tv = (TextView)getActivity().findViewById(R.id.introTimeLeft);
public void onTick(long millisUntilFinished) {
Calendar cal = Calendar.getInstance();
cal.set(2012, 8, 29, 10, 0);
long endTime = cal.getTimeInMillis();
long currentTime = System.currentTimeMillis();
long remaining = currentTime - endTime;
long hours = remaining / 3600000;
long mins = remaining / 60000 % 60;
long seconds = remaining / 1000 % 60;
long days = hours / 24;
String remainingText = String.valueOf(days) + " days";
Log.i("countdown",String.valueOf(days));
tv.setText("Days left: " + days);
}
public void onFinish() {
Log.i("countdown","CD Finished");
tv.setText("CD Finished!");
}
}.start();
}
Note that the textbox value is just for testing right now, but i can't seem to get it to display the countdown.
Also is this the best approach?
Here are the values of the variables if I run your code:
endTime = 1348902045437
currentTime = 1340645325437
remaining = -8256720000
seconds = 0
as you see seconds == 0, and this is the reason.
Also note that the first argument in the CountDownTimer(long millisInFuture, long countDownInterval) constructor is
The number of millis in the future from the call to start() until the
countdown is done and onFinish() is called.
So a fixed code would be:
Calendar cal = Calendar.getInstance();
cal.set(2012, 8, 29, 10, 0);
long endTime = cal.getTimeInMillis();
long currentTime = System.currentTimeMillis();
long remaining = endTime - currentTime;
new CountDownTimer(remaining, 1000) {
...
UPDATE:
It is odd it does not update the text view. The only idea I can propose is to run update calls on the main UI thread. It should be something like this:
public void onTick(long millisUntilFinished) {
final String days = .. // some code to generate days
getActivity().runOnUiThread(new Runnable() {
public void run() {
tv.setText("Days left: " + days);
}
});
}
public void onFinish() {
Log.i("countdown","CD Finished");
getActivity().runOnUiThread(new Runnable() {
public void run() {
tv.setText("CD Finished!");
}
});
}
If this doesn't help - then I'm out of ideas.