I need to to show a countdown timer with 2 time periods, for example i need it to count down a 45 sec, then count down 15 sec and then loop it all over again 4 times.
I tried this code but it seems to start all the timers at ones. I want at to start the first timer and wait till it finish and then start the second timer wait till it finish and then loop it again.
what should i do??
for (int i = 0; i < labsNum; i++) {
currLabTV.setText("LAB " + (i + 1));
if(isWorking) {
timer = new WorkCounter(workNum * 1000, 1000);
timer.start();
}
if(!isWorking){
timer = new WorkCounter(restNum * 1000, 1000);
timer.start();
}
}
i extended the CountDownTimer class.
public class WorkCounter extends CountDownTimer {
public WorkCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
String ms = String.format("%02d:%02d" , TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished), TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished));
timeTV.setText(ms);
}
#Override
public void onFinish() {
if(isWorking) {
workoutSign.setText("REST");
}else {
workoutSign.setText("WORKOUT");
}
isWorking = !isWorking;
}
}
Related
I want run timer for about 30000 ms and up to 8 or more times each so here is my loop but it runs all timers at once after 30000ms
public void repeatTimerTask() {
repeat = 8; // need to run 30 sec timer for 8 times but one after one
startTimer(30000); // firsat timer for 30 sec
Handler handler = new Handler();
for (int a = 1; a<=repeat; a++) {
final int finalA = a;
handler.postDelayed(new Runnable() {
#Override
public void run() {
startTimer(30000);
}
}, 30000); // delay until to finish first timer for 30 sec
}
}
To run a timer for n seconds you can use CountDownTimer
Declare two varibales globbaly. One for number of times you want to repeat. and one to keep the count of repetaion.
private int NUM_REPEAT = 4;
private int REPEAT_COUNT = 0;
Then call this method wherever you want. One thing to note if you want to run this loop 5 times you have to give number of repeation 4. Cause to satrt this function you have to call it so that will not come in count.
private void startTimer() {
new CountDownTimer(3000, 1000) {
int secondsLeft = 0;
public void onTick(long ms) {
if (Math.round((float) ms / 1000.0f) != secondsLeft) {
secondsLeft = Math.round((float) ms / 1000.0f);
// resend_timer is a textview
resend_timer.setText("remaining time is "+secondsLeft);
;
}
}
public void onFinish() {
Log.d(TAG, "timer finished "+REPEAT_COUNT);
if (REPEAT_COUNT <= NUM_REPEAT) {
startTimer();
REPEAT_COUNT++;
}
}
}.start();
}
Please try the below code, and call 'startTimer' method where you first want to start your timer :
private int startTimerCount = 1, repeat = 8;
private void startTimer(){
// if startTimerCount is less than 8 than the handle will be created
if(startTimerCount <= repeat){
// this will create a handler which invokes startTimer method after 30 seconds
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
startTimer();
}
}, 30000);
// do what you want
Toast.makeText(this, "startTimer " + startTimerCount, Toast.LENGTH_SHORT).show();
}
startTimerCount++;
}
I have a Timer in my Code, but the debugger jumps not into it. When it arrives at "timer.schedule()", jumps directly behind it and is not instancing the anonymous TimerTask. Can anyone help me why?
CODE:
timer = new Timer();
lastTimestamp = calendar.getTimeInMillis() / 1000;
// WHEN DEBUGGING IT JUMPS FROM THIS LINE
timer.schedule(new TimerTask() {
#Override
public void run() {
long now = calendar.getTimeInMillis() / 1000;
secondsElapsed += now - lastTimestamp;
lastTimestamp = now;
// Abbruch-Bedingung
if(secondsElapsed == totalSeconds)
{
// TODO:
Log.d("MainActivity", "Zeit abgelaufen");
}
else
{
int minutes = (int)secondsElapsed / 60;
int seconds = secondsElapsed - (minutes * 60);
final String newValue = String.format("%02d:%02d", minutes, seconds);
runOnUiThread(new Runnable() {
#Override
public void run() {
timerText.setText(newValue);
}
});
}
}
}, 0, 1000);
// TO THIS LINE
Those lines are executing in another thread. When that thread is scheduled to run they will run. If you place a breakpoint there you will see them execute
EDIT
try {
Timer timer = new Timer();
long lastTimestamp = System.currentTimeMillis() / 1000;
// WHEN DEBUGGING IT JUMPS FROM THIS LINE
timer.schedule(new TimerTask() {
#Override
public void run() {
System.out.println("WWWWWWW");
}
}, 0, 1000);
}
catch(Exception x){
}
}
This code executes with no problem. The thread is executed inside the timer
I created an application that can call using our SIP server. Now I want to do is to show the user how long his call has been on going. My script is actually working but I noticed that the longer the call, the laggy my app becomes. Here's the snippet of my code
Handler h = new Handler(Looper.getMainLooper());
_isOnCall = true;
long time = 0;
int x = 0;
while(_isOnCall) {
if (_isOnCall){
final int counter = 1 + x;
time += 1000;
h.postDelayed(new Runnable() {
#Override
public void run() {
(TargetDetailsActivity.this).runOnUiThread(new Runnable() {
#Override
public void run() {
final int seconds = counter % 60;
final int minutes = (counter % 3600) / 60;
final int hours = counter / 3600;
callcounter.post(new Runnable() {
#Override
public void run() {
callcounter.setText(String.format("%02d:%02d:%02d", hours, minutes, seconds));
}
});
}
});
}
}, time);
x++;
}else{
break;
}
}
Basically what the code does is just to count the seconds/minutes/hour he's been on the phone. When he hangs up, I call the code below:
_isOnCall = false;
h.removeCallbacksAndMessages(null);
I'm not sure what causes the lag. Help! Thanks.
UPDATE
I was able to make this working by utilizing galvan's suggestion using Timer. Here's my code for future reference:
private Timer myTimer;
private int counter_time=0;
public void onCallEstablished() {
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 1000);
}
private void TimerMethod()
{
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
counter_time++;
int seconds = counter_time % 60;
int minutes = (counter_time % 3600) / 60;
int hours = counter_time / 3600;
callcounter.setText(String.format("%02d:%02d:%02d", hours, minutes, seconds));
}
};
public void releaseCall(){
if(myTimer != null){
myTimer.cancel();
myTimer.purge();
counter_time = 0;
}
}
It looks like every Runnable saves a reference to his parent object, a nested Runnable in this case. Try to take an heap snapshot for detecting a memory issues to see if this is the case here.
You can also make a repeat task with time interval, and stop the loop when the call ends.
Timer timer = new Timer();
TimerTask myTask = new TimerTask() {
#Override
public void run() {
// whatever you need to do every 2 seconds
}
};
timer.scheduleAtFixedRate(myTask,
firstTime,
period);
for more info about timer you can take a look at the docs
I have a fairly simple JavaFX GUI application which has an label that shows how much time is left until a certain action starts. To achieve this, I've created a DownloadTimer class as shown below:
public class DownloadTimer(){
private int minutes;
private int seconds;
private Timer innerTimer = new Timer();
private TimerTask innerTask;
private boolean isActive;
public DownloadTimer(int minutes, int seconds) {
if (seconds > 60) {
int minToAdd = seconds / 60;
this.minutes = minutes;
this.minutes += minToAdd;
this.seconds = seconds % 60;
} else {
this.minutes = minutes;
this.seconds = seconds;
}
}
public void start() {
innerTask = new TimerTask() {
#Override
public void run() {
isActive = true;
System.out.println(getTime());
if (seconds == 0 && minutes > 0){
minutes -= 1;
seconds = 59;
} else if (seconds == 0 && minutes == 0){
isActive = false;
innerTimer.cancel();
innerTimer.purge();
System.out.println("DownloadTimer DONE");
} else {
seconds -= 1;
}
}
};
innerTimer.scheduleAtFixedRate(innerTask, 0, 1000);
}
}
And then, I'm creating the DownloadTimer object and starting the countdown from my Main (JavaFX) class:
/*
code omitted for better readability
*/
downloadTimer = new DownloadTimer(0, 5);
// label gets the .getTime() value, which returns a formatted String like "00:05", "00:04", etc.
lblTimer.setText( downloadTimer.getTime() );
// start the countdown
downloadTimer.start();
// create a new timer which checks if the downloadTimer is still counting
final Timer timer = new Timer();
TimerTask timerTask = new TimerTask(){
#Override
public void run(){
if (downloadTimer.getIsActive() == false){
timer.cancel();
timer.purge();
System.out.println("GUI timer DONE");
} else {
// if it's still running, then continuously update the label's text
lblTimer.setText( downloadTimer.getTime() );
// this is where I get the error described below
}
}
};
// repeat after 1000ms
timer.scheduleAtFixedRate(timerTask, 0, 1000);
The problem I'm encountering with this is that I can't set the label text with lblTimer.setText( downloadTimer.getTime() ); from the Main class, and the error I'm getting is TimerThread.run() line: not available [local variables unavailable] as seen here.
I've read about ScheduledThreadPoolExecutor and Java Timer vs ExecutorService, but I'm curious if this can be done using two separate Timers and TimerTasks. Any help and/or tips would be greatly appreciated.
I'm surprised you're not seeing an exception. To update a label from a separate thread, one needs to schedule an update to be run in the FX thread:
Platform.runLater(new Runnable() {
public void run() {
lblTimer.setText(downloadTimer.getTime());
}
});
I am new to countdown timer so I have no idea about this issue. I tried many things but I didn't get what I expected.
This is my code for the timer. It is a class within a class as usual.
// TIMER
public class Timer extends CountDownTimer {
public Timer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
//getNgo(true, score, tries, secLeft);
}
#Override
public void onTick(long millisUntilFinished) {
//secLeft = millisUntilFinished;
int sec = (int) (millisUntilFinished / 1000);
sec = sec % 60;
int min = sec / 60;
tvTime.setTextColor(Color.WHITE);
if (sec <= 10) {
animScale(tvTime);
tvTime.setTextColor(Color.RED);
tvTime.setText("" + min + ":" + sec);
if (sec < 10) {
tvTime.setTextColor(Color.RED);
tvTime.setText("" + min + ":0" + sec);
}
} else {
tvTime.setText("" + min + ":" + sec);
}
}
}
So, I just wanted to know how to deduct 3 seconds (that will be 3000 ms) when I push the button and the timer that is displayed by the textview will go on ticking but the time has already been deducted. And where do I put the code. Thanks!
When I've had to do this with tasks scheduled to take place in a fixed time, I've:
Cancelled the original task.
Submitted a new one with the new time period.
I suspect that this is a more standard pattern than your use of Timer anyway.
e.g.:
private final Runnable task = new Runnable() { #Override public void run() { /* ... */ } };
private final ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor();
private final long initialSeconds = 3;
public void submitTask() {
stpe.schedule(task, initialSeconds, TimeUnit.Seconds());
}
public void subtractSeconds(long sec) {
if(stpe.remove(task)) {
stpe.schedule(task, Math.Max(initialSeconds - sec, 0), TimeUnit.Seconds);
}
}
You will need to figure out:
how to ensure task is only initially-submitted once and keep track of fixed variable
whether you need one fixed final task or that task to be changed
concurrency/multithreading issues if the task can be submitted more than once
I've implemented a simple countdown using one of the stackoverflow posts
// gets current time
long timeNow = System.currentTimeMillis();
/* timer holds the values of the current second the timer should display
* requiredTime is the start value that the countdown should start from
* startTime is the time when the application starts
*/
timer = requiredTime - (timeNow - startTime) / 1000;
if (timer >= 0)
timer.setText(String.valueOf(timer));
To subtract the timer, subtract requiredTime and it will work. Because you've changed the reference value.
// Override onClickListener and add the line
// to deduct 3 seconds
requiredTime -= 3;
You can't. You have to write your own CountDownTimer. Copy original code and add method
public synchronized void addTime(long millis) {
mStopTimeInFuture += millis;
}
Then set onClickListener to the button
bt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
timer.addTime(-2000);
}
});
Here is full sample code