I'm developing an application which is a typing test that allows users to test their typing speed by typing a passage in a specific period of time. The problem is that users are still be able to type after that period of time. How would I stop the timer after that specific time in order to stop users from typing?
CountDownTimer cdTimer; cdTimer=new CountDownTimer(30100, 1000) {
public void onTick(long millisUntilFinished) {
timerTextView.setText(String.valueOf(millisUntilFinished / 1000) + "s");
}
public void onFinish() {
playAgainButton.setVisibility(View.VISIBLE);
timerTextView.setText("0s");
}
}.start();
You can do as follow
CountDownTimer cdTimer; cdTimer=new CountDownTimer(30100, 1000) {
public void onTick(long millisUntilFinished) {
timerTextView.setText(String.valueOf(millisUntilFinished / 1000) + "s");
}
public void onFinish() {
<WriteHearActivityName>.this.finish();
startActivity(<WriteHearActivityName>.this,ResultActivity.class);
}
}.start();
This will solve your issue +1
Related
I am trying to use countdowntimer in Android, following is a small testcode to understand its behaviour
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
System.out.println("tick");
}
public void onFinish() {
System.out.println("finish");
}
}.start();
System.out.println("done");
If I place this snippet in MainActivity of my project it runs fine, but not in a standalone class. Why ?
Also, does countdown timer run on main thread itself, or it spawns another thread ?
Your code includes 2 parts:
CountDownTimer cdt = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
System.out.println("tick");
}
public void onFinish() {
System.out.println("finish");
}
};
The first part is instantiating a CountDownTimer object, you can place this code any where, on any thread, because only object was created, it does nothing.
The second part is:
cdt.start();
You should notice that CountDownTimer must be start from Main Thread (call it from onCreate or onResume... of an Activity). So if you place your code in another Class, it is not the problem, you must sure that start() function called on Main Thread.
//Update:
You know, the onTick and onFinish function of CountDownTimer always is called on Main Thread. CountDownTimer will not run any thread.
It's its code:
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}
Very simply, CountDownTimer will send a message by a Handler.
And this is Handler:
// handles counting down
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 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);
}
}
}
};
The Handler will send a delay message for calling next onTick() or onFinish(). So it must use Main Thread (or Main Looper). If you want it run in a custom thread, reimplement it in your way :D
I am writing an HIIT (High Intensity Interval Training) activity for which I am implementing an interval timer. The CountDownTimer is supposed to finish 5 minutes of Warm-Up, then proceed to time the HIIT workout.
public class WarmUpActivity extends ActionBarActivity{
TextView Mode;
TextView Time;
int minutes;
long time_remaining;
boolean warmup_finished;
private CountDownTimer HIIT_Timer;
private void StartTimer() {
HIIT_Timer = new CountDownTimer(time_remaining, 1000) {
#Override
public void onTick(long millisUntilFinished) {
time_remaining = millisUntilFinished; //in case activity is paused or stopped
Time.setText(" " + (int)floor(millisUntilFinished / 60000) + ":" + ((millisUntilFinished / 1000) % 60));
if (warmup_finished == true) { //if we are in HIIT mode
if ((int)millisUntilFinished % 60000 == 0) { //every minute
if (Mode.getText() == "Low Intensity")
Mode.setText("High Intensity");
else
Mode.setText("Low Intensity");
}
}
}
#Override
public void onFinish() {
if (warmup_finished==false){
Mode.setText("Low Intensity");
warmup_finished = true;
HIIT_Method();
return;
}
else {
Completed_Method();
return;
}
}
}.start();
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.hiit_layout);
Mode=(TextView) findViewById(R.id.mode);
Time=(TextView) findViewById(R.id.time);
warmup_finished=false;
Mode.setText("Warm-Up");
time_remaining=5*60000; //5 minutes when created
}
#Override
public void onStart(){
super.onStart();
StartTimer();
return;
}
private void HIIT_Method(){
minutes=getIntent().getIntExtra(SelectHIITDuration.MINUTES, 0);
time_remaining=minutes*60000;
StartTimer();
return;
}
private void Completed_Method(){
Mode.setText("Workout Completed");
}
}
When warmup is finished and onFinish() is called for the first time, HIIT_Method is called, in which the HIIT timer is supposed to start with user specified duration. The problem is, after the new timer is declared using Start_Timer(), somehow Completed_Method is called. It can only be called from onFinish(). Why is onFinish() being called after I declare a new timer?
We need to move your call to startTimer from onStart to onCreate.
The issue here is understanding the Android lifecycle for an activity. A very good explanation by someone with better understanding than I is explained here.
Now from what I understand, we typically don't touch onStart until we start worrying about service binding and database queries, but other developers may think differently.
The official android documentation on an activity's lifecycle can be found here
I ran across an issue, I'm using a count down timer in a method as shown below, and call it at certain places in my application i.e. scoreTimer(); I'm having a hard time figuring out how to stop it, I noticed a .start() method at the end of CountDownTimer and I assume there should be a .stop() method as well, but how can I apply it when I use a method - scoreTimer()?
public void scoreTimer() {
new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
getTimer.setText("" + millisUntilFinished / 1000);
}
public void onFinish() {
cycleState = 1;
expressionCycle();
if (currentCycle <= 10) {
scoreTimer();
}
System.out.println("SCORE: " + totalScore);
}
}.start();
}
Assign the timer to a variable like this:
CountDownTimer mTimer = new CountDownTimer...
And then you can invoke
mTimer.cancelTimer()
i have countdown timer with this code:
CountDownTimer CountdownTimer = new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
txttime.setText( millisUntilFinished / 1000);
}
public void onFinish(){
timeout_stage();
CountdownTimer.cancel();
}
};
i start it with this code:
CountdownTimer.start();
and then i stop it by this code:
CountdownTimer.cancel();
but after cancelling, when i start it again my CountdownTimer works but the text on the txttime is not change!! (but first time works perfectly)
how i can fix it?
For my Android application there is a timer that measures how much time has passed. Ever 100 milliseconds I update my TextView with some text like "Score: 10 Time: 100.10 seconds". But, I find the TextView only updates the first few times. The application is still very responsive, but the label will not update. I tried to call .invalidate(), but it still does not work. I don't know if there is some way to fix this, or a better widget to use.
Here is a example of my code:
float seconds;
java.util.Timer gametimer;
void updatecount() { TextView t = (TextView)findViewById(R.id.topscore);
t.setText("Score: 10 - Time: "+seconds+" seconds");
t.postInvalidate();
}
public void onCreate(Bundle sis) {
... Load the UI, etc...
gametimer.schedule(new TimerTask() { public void run() {
seconds+=0.1; updatecount();
} }, 100, 100);
}
The general solution is to use android.os.Handler instead which runs in the UI thread. It only does one-shot callbacks, so you have to trigger it again every time your callback is called. But it is easy enough to use. A blog post on this topic was written a couple of years ago:
http://android-developers.blogspot.com/2007/11/stitch-in-time.html
What I think is happening is you're falling off the UI thread. There is a single "looper" thread which handles all screen updates. If you attempt to call "invalidate()" and you're not on this thread nothing will happen.
Try using "postInvalidate()" on your view instead. It'll let you update a view when you're not in the current UI thread.
More info here
Use Below code to set time on TextView
public class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
#Override
public void onFinish() {
ExamActivity.this.submitresult();
}
#Override
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
int seconds = (int) (millis / 1000) % 60;
int minutes = (int) ((millis / (1000 * 60)) % 60);
int hours = (int) ((millis / (1000 * 60`enter code here` * 60)) % 24);
String ms = String
.format("%02d:%02d:%02d", hours, minutes, seconds);
txtimedisplay.setText(ms);
}
}
There is one more way to change text each second; this is ValueAnimator. Here is my solution:
long startTime = System.currentTimeMillis();
ValueAnimator animator = new ValueAnimator();
animator.setObjectValues(0, 1000);
animator.setDuration(1000);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
long currentTime = System.currentTimeMillis();
String text = TimeFormatUtils.formatTime(startTime - currentTime);
yourTextView.setText(text);
}
#Override
public void onAnimationRepeat(Animator animation) {
long currentTime = System.currentTimeMillis();
String text = TimeFormatUtils.formatTime(startTime - currentTime);
yourTextView.setText(text);
}
});
animator.start();