I want to create an incrementing second timer like a stopwatch.
So I want to be able to display the seconds and minutes incrementing in the format 00:01...
Google only brings up 24 hour clock examples, I was wondering could anyone get me started with an example or tutorial of what I want to do?
Edit:
Here is what I have using the Chronometer in Android so far
In onCreate()
secondsT = 0;
elapsedTimeBeforePause = 0;
stopWatch.start();
startTime = SystemClock.elapsedRealtime();
stopWatch.setBase(elapsedTimeBeforePause);
stopWatch.setOnChronometerTickListener(new OnChronometerTickListener(){
#Override
public void onChronometerTick(Chronometer arg0) {
//countUp is a long declared earlier
secondsT = (SystemClock.elapsedRealtime() - arg0.getBase()) / 1000;
String asText = (secondsT / 60) + ":" + (secondsT % 60);
//textGoesHere is a TextView
((TextView)findViewById(R.id.time)).setText(asText);
}
});
In onDestroy()
#Override
public void onDestroy() {
inCall = false;
elapsedTimeBeforePause = SystemClock.elapsedRealtime() - stopWatch.getBase();
super.onDestroy();
}
The above compiles and runs but the TextView never increments, it always stays at 0, can anyone see why?
I'm assuming you aren't aware of the Android Chronometer - it already has a basic stopwatch function. You need to work with its peculiarities a bit, but it's not hard to get it to do what you want once you understand how it works.
There are a few ways that time is calculated on the phone, but the two main ones are:
The "real time", such as right now according to my computer clock, it is 11:23am in England. However, this can change if my computer contacts a time server and is told it has the wrong time, or if I were travelling with a laptop and crossed a timezone boundary. Using this would wreak havoc with your stopwatch as the measured time could change at any time.
The "elapsed time since boot", which is the number of milliseconds since the phone was switched on. This number doesn't bear any relation to the real time it is, but it will behave in a perfectly predictable manner. This is what the Android Chronometer uses.
The Chronometer is essentially a 'count up' timer, comparing the current SystemClock.elapsedRealtime() against the elapsedRealtime() that was set fot its base time. The difference between the two, divided by 1000, is the number of seconds since the timer was started. However, if you stop the timer and then start it again, you will get a counter-intuitive result - the timer will show the elapsed time as if it had never stopped. This is because you need to adjust its base time to take into consideration the time it was stopped. This is simple to do:
// When you're stopping the stopwatch, use this
// This is the number of milliseconds the timer was running for
elapsedTimeBeforePause = SystemClock.elapsedRealtime() - timer.getBase();
// When you're starting it again:
timer.setBase(SystemClock.elapsedRealtime() - elapsedTimeBeforePause);
Edit: Here is the full code for a basic stopwatch, which displays your time in a TextView rather than the Chronometer widget declared in your XML file.
public class TestProject extends Activity {
TextView textGoesHere;
long startTime;
long countUp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Chronometer stopWatch = (Chronometer) findViewById(R.id.chrono);
startTime = SystemClock.elapsedRealtime();
textGoesHere = (TextView) findViewById(R.id.textGoesHere);
stopWatch.setOnChronometerTickListener(new OnChronometerTickListener(){
#Override
public void onChronometerTick(Chronometer arg0) {
countUp = (SystemClock.elapsedRealtime() - arg0.getBase()) / 1000;
String asText = (countUp / 60) + ":" + (countUp % 60);
textGoesHere.setText(asText);
}
});
stopWatch.start();
}
}
In your main.xml you need to have this
<Chronometer android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/chrono"
android:visibility="gone"/>
There's undoubtedly a way to get the Chronometer to work without declaring it in the XML file, but the constructor Chronometer stopwatch = new Chronometer(this); didn't work properly.
The above code displays the elapsed time in a very basic way. For example, if only 5 seconds have gone by, it will show 0:5 rather than the 0:05 you probably want. Fixing that is not hard to do, but I'll leave that for you to work out! :)
How about this one Digital Clock.
But basically you should be able to find many java implementations by googling for keywords like java, stopwatch, digital clock, ...
You could take a look at Stopwatch Applet and modify as needed (Oops no source with this one)
Related
I am thinking about making an android app to support a game of mine, and I can't find info on how to do it. Here is an app explanation:
The app should have two timers (both set for x minutes). When first player starts his turn (by a button click) his time starts running out. when first player makes his move, he should click his time to stop it, and player two starts his turn.
NOW, the problem I can't find a solution for - When player one takes his turn, time that he loses should pass to the other player's timer.
Example: Both players start with a 5 minute timer. If player one takes 30 second for his turn, his time should go down to 04:30, at which time he clicked on his timer. During that time, for each second he lost, the other player gained time on his timer, so at the beginning of his turn, his time is 05:30. The time goes back and forth, and the player whose timer runs out loses the game.
Any idea how to do this?
I am still stuck to the idea on how to make it, so I have no code to share.
Thank you all for your answers, and effort in helping me, if you have a question I haven't covered, I will gladly answer it.
First, you will need to instantiate class of CountDownTimer everytime you click on button.
For reference check here: https://developer.android.com/reference/android/os/CountDownTimer.html
You have two parameters long millisInFuture, long countDownInterval
Before you start, you will need to create two global variables one for first player, and one for second player like this:
long firstPlayerRemainingTime = 5 * 60 * 1000; // start time 5 minutes
long secondPlayerRemainingTime = 5 * 60 * 1000;
long limitedTime = 30 * 1000; // 30 seconds
CountDownTimer mCountDownTimer;
Now we have came to the most important part and that is logic inside onClickListener method
I don't know if there are two buttons or one, but I will go with two buttons:
btnFirstPlayer.setTag(1); // start timer
btnFirstPlayer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (btnFirstPlayer.getTag() == 1) {
startTimer();
} else {
stopTimer();
}
});
private void startTimer() {
long startTime = firstPlayerRemainingTime;
btnFirstPlayer.setTag(2); // stop timer
btnFirstPlayer.setText("Stop");
mCountDownTimer = new CountDownTimer(firstPlayerRemainingTime, 1000) {
public void onTick(long millisUntilFinished) {
firstPlayerRemainingTime = millisUntilFinished;
tvPlayerOneTimer.setText("" + firstPlayerRemainingTime / 1000)
// Here you would like to check if 30 seconds has passed
if ((startTime / 1000) - (limitedTime / 1000)
== (firstPlayerRemainingTime / 1000)) {
stopTimer();
}
// Here you would like to increase the time of the second player
secondPlayerRemainingTime = ++1000;
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
}
}
private void stopTimer() {
btnFirstPlayer.setTag(1);
btnFirstPlayer.setText("Start");
mCountDownTimer.cancel();
// I guess here starts second player move
}
The same logic would go for second player. Let me know if this helped you or if I need to explain anything.
I'm building an Android game and I need to display a countdown. In order for the users to not cheat I can't stop this countdown if user changes app, because they would have more time to think the answer.
What I need to do is to let the CountDownTimer continue working even if my app is not currently on front (onPause has been called).
I wonder if the code I have (which seems to work) will do the trick, or if under some circumstances it would fail.
Right now the countdown continues and when it gets 0, the result screen is displayed over the current app (which, of couse, is not what I want).
I think for this second question the solution would be to store a variable or something and check that before launching results screen.
So, to sum up, what I want is the countdown to continue even if the user changes the current app, but when the countdown gets to 0, don't show the result screen until user comes back to the game.
My code is as follows:
new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
tvTime.setText(String.valueOf(millisUntilFinished / 1000));
}
public void onFinish() {
startActivity(new Intent(GameActivity.this, ResultActivity.class));
}
}.start();
Thank you.
Just to give you an idea of what you should do. Probably should use SystemClock.elapsedTime().
public class CountdownTimer {
private final long startTime = currentTime();
private final long totalTime;
private boolean isFinished = false;
public CountdownTimer(long millis) {
totalTime = millis;
}
public long timeLeft() {
return totalTime - (currentTime() - startTime);
}
public boolean isFinished() {
return isFinished || (isFinished = timeLeft() < 0);
}
protected long currentTime() {
return System.currentTimeMillis();
}
}
If the user closes your app then you shouldn't reopen it on them. Let them open the app themselves and find out that their time is up, or display a notification.
Storing it in a variable and displaying it as long as it's not paused seems like the simplest solution. What I'd do is in the onPause method set some global variable to true, and something like
if(!thatGlobalVariable)
{
displayVariable()
}
You know what I mean, it's your idea relayed back at you.
Sorry this wasn't much help, and you were probably looking for some other more extravagant solution. I'd do this in the meantime until you get an answer that is more suitable.
Also, I think it's pretty cool if the timeout message pops up when minimized. So the person might be looking up something in google then all of a sudden "Time up, you failed". People like games that torment them into playing more.
Along with all the other game state you save in the SavedInstance you could save the current time. When user resumes your app you can compare the new time against the saved value to determine whether the time is up. Then the message can be displayed.
I'm making fast forward button in my Mp3 player. I wrote already code for this, but have problem how to implement timer to jump 5% forward? I mean when I press button timer should jump 5% forward of total long song. This is my fastForward method.
public void FastForward(){
try {
//songTotalLength = fis.available();
fis.skip((long) ((songTotalLength * 0.05)));
} catch (IOException e) {
e.printStackTrace();
}
}
And here is the button method:
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
bar+=5;
}
And this one is for timer:
private void setTime(float t) {
int mili = (int) (t / 1000);
int sec = (mili / 1000) % 60;
int min = (mili / 1000) / 60;
start.set(Calendar.MINUTE, 0);
start.set(Calendar.SECOND, 0);
end.set(Calendar.MINUTE, 0 + min);
end.set(Calendar.SECOND, 0 + sec);
timer = new javax.swing.Timer(1000, new TimerListener());
percent = (float)100/(min*60+sec);
}
You're already redundantly tracking progress in two variables fis and bar. For the sake of good design, use one of those to determine elapsed time rather than using yet another variable for the same purpose.
but have problem how to implement timer to jump 5% forward?
You seem to have mistaken the purpose of a Timer. According to the Timer class documentation, it:
Fires one or more ActionEvents at specified intervals.
So the timer is not meant to keep track of how much time has elapsed. It will simply invoke the actionPerformed(ActionEvent) method of your TimerListener once per second (every 1000 milliseconds) as you have it configured.
For a more complete answer, please post the code for your TimerListener class.
Notes
It seems that your setTime(float) method is meant to be called repeatedly, so this method should not be initializing the timer variable. Rather initialize the timer once and leave it alone to do its job.
I'm assuming you intended the supplied float parameter t to represent microseconds.
The float data type has only 7 digits of precision. This could be fine since you're interested only in minutes and seconds, otherwise float is only good for up to about four months of seconds before losing accuracy.
It seems like you wanted your button click handler to do this (increment bar sooner):
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
bar+=5; // increment bar before checking complete, and before setting progress
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
}
Below I have a Runnable "updater" ...and an OnClick function that uses Handler.PostDelayed function to run the runnable after a delay...
After a little editing, cutting of useless parts here are the functions:
(passtog = Toggle Button)
final Runnable updater = new Runnable() {
#Override
public void run() {
if (passTog.isChecked()) {
now = System.currentTimeMillis();
time = now - init;
if (time > 5000) {
Toast.makeText(getApplicationContext(), "WAKE UP !",
Toast.LENGTH_SHORT).show();
}
handler.postDelayed(this, 25);
}
}
};
passTog.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
init = System.currentTimeMillis();
flag = true;
handler.postDelayed(updater,
(new Random().nextInt(4000) + 3000));
}
});
}
Explaination
Basically, The user toggles the Toggle button. Now it's on: The runnable can run completely (Everything is in the if block).
If the user doesn't press the button again, and switches it off The app sends a Toast "Wake Up!" ..It runs and checks every 25 millisecs to update the time...
Pretty straightforward... Yet I'm having a problem.
Before the program actually gets to the runnable, I absolutely NEED there to be a minimum time delay of 3 seconds + Some Random value ... So it varies between 3 sec - 7 sec. It SHOULD vary between 3-7 , but it doesn't.
When I run it: The problem
I notice that the first time, it works great... I get atleast a 3 sec delay + a random value= Perfect
The second time, that is after the switch goes on ->off-> on : Now It acts like it doesn't see the +3000 ...and just the ~randInt(4000) function... So it may give 0 sec or it may give 4 sec delay...
In all my experience, I've never really come across this.. I've rewritten the entire code, My other apps use this function in exactly the same sytax and seem to do pretty great.. Why is this creating a problem ? Could the Toast's time possibly be causing a problem..
How to solve this ?
(I'm open to other methods, preferably quick to implement. I want a minimum 3 sec delay which I'm not getting for some reason... I need the UI to be responsive though So no thread sleeping.)
You probably should call Handler.removeCallbacksAndMessages(null) when the switch goes off.
I've looked everywhere for an answer but cannot find one for my situation. I have a couple problems and also wonder how to include millisecond countdown as well. I'm trying to get a countdown timer in the format 00.00 (seconds.milliseconds). A button is used to start the timer. The times I use depend on the button pressed, 5, 10, 15, 30, or 90 seconds. I'll just says its hard coded to 5000 ms to make simpler for now.
long timeSecs = 5000; // really timeSecs is dynamic but for the sake of simplicity
long countDownInterval = 1000; // this is a static value
TextView TVcountDown = (TextView)findViewById(R.id.TVcountDown);
public void createTimer() {
new CountDownTimer(timeSecs, countDownInterval) {
public void onTick(long millisUntilFinished) {
TVcountDown.setText(millisUntilFinished / 1000); // error here on
//.setText unless I cast to an int, which all values are long so I'm not sure why
}
#Override
public void onFinish() {
TVcountDown.setBackgroundColor(R.color.solid_red); // error here
TVcountDown.setTextColor(R.color.white); // error here
TVcountDown.setText("Expired"); // it will make it here
// It doesn't count down, just goes straight to onFinish() and displays "Expired"
}
}.start();
}
Thanks in advance. I've been beating my head against the desk for awhile now.
Try this.
For setText
TVcountDown.setText("" + (millisUntilFinished / 1000));
For the color
Resources res = getResources();
TVcountDown.setBackgroundColor(res.getcolor(R.color.solid_red));
TVcountDown.setTextColor(res.getcolor(R.color.white));
you should get color from the color resource before setting.