I define the countdowntimer here.
Then, new countdowntimer is defined for this variable in an onclick method:
public void showQuestion(int questionNumber){
questionTimer = new CountDownTimer(10500,1000) {
#Override
public void onTick(long millisUntilFinished) {
remainingTime.setText(Long.toString(millisUntilFinished/1000));
}
#Override
public void onFinish() {
remainingTime.setText("0");
showCorrectAnswer();
}
}.start();
}
Then i cancel this timer on another button' onclick method;
public void selectOption(View view) {
questionTimer.cancel();
}
In this time, it is succesfully cancelled. Then i am doing the same again. showQuestion method is working in the same way.
public void showQuestion(int questionNumber){
questionTimer = new CountDownTimer(10500,1000) {
#Override
public void onTick(long millisUntilFinished) {
remainingTime.setText(Long.toString(millisUntilFinished/1000));
}
#Override
public void onFinish() {
remainingTime.setText("0");
showCorrectAnswer();
}
}.start();
}
It is started succesfully. When i want to cancel this timer on another button onclick method, it is not working. Not any error. I hope it could be clear. Thank you so much.
The issue with your code is the timer can be started multiple times (sometimes not intentional) before the first timer is finished or cancelled. In that case, when you try to cancel it, you can only cancel the first timer. To solve this issue, you only have to check whether the timer is running, if it is running, wait for it to finish or cancel.
Define a global parameter:
Boolean timerRunning = false;
public void showQuestion(int questionNumber){
if (timerRunning) return;
timerRunning = true;
questionTimer = new CountDownTimer(10500,1000) {
#Override
public void onTick(long millisUntilFinished) {
remainingTime.setText(Long.toString(millisUntilFinished/1000));
}
#Override
public void onFinish() {
remainingTime.setText("0");
showCorrectAnswer();
timerRunning = false;
}
}.start();
}
Your selection option method can be changed to below: check if the timer is null before cancelling it.
public void selectOption(View view) {
if (questionTimer != null) questionTimer.cancel();
timerRunning = false;
}
public void selectOption(View view) {
questionTimer.cancel();
questionTimer = null;
}
Related
I have implemented one counter and onFinish() of first counter,I started second counter but the first counter not able to finish.Text "Bye Guyz" remain for some time so how to finish the text.
Please help me.
Thanks in advance.!!!
Code :-
counter= new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished) {
if (count == 0) {
tv.setText("First counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Guyz");
}
}
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
else if(flag) {
counter1 = new CountDownTimer(9000, 1000) {
public void onTick(long millisUntilFinished) {
flag = false;
tv.setText("Second counter");
tv2.setVisibility(View.VISIBLE);
tv2.setText("Hello Girls");
count = 0;
}
public void onFinish() {
tv2.setVisibility(View.VISIBLE);
tv2.setText("Bye Girls");
count = 0;
}
}.start();
Did you "debug" the code to be sure the code is arriving to counter1 = new CountDownTimer(9000, 1000)?
Are you sure when the first counter arrives to onFinish() the flag variable is true?
Why do you call counter.cancel() in onFinish() when obviously the counter is already over?
public void onFinish() {
if(!flag) {
tv2.setText("Bye Guyz");
count = 0;
try {
counter.cancel();
}catch (Exception e){}
}
If you say your tv2 displays "Bye Guyz" it means that your flag is set to false, so the "else if" part is not being executed. onFinish() is only executed once, so you need to make sure the flag is set for true to start the second counter.
Also you shouldn't cancel your counter in onFinish() because it's already finished.
Here is my alternative is as follows
Create the custom Counterextending Thread
class Counter extends Thread {
private long timeOne, timeTwo;
private OnCounterFinishedListener mCounterFinishedListener;
private Thread t;
Activity activity = null;
Counter(Context context){
t = new Thread(this);
activity = (Activity)context;
}
#Override
public void run() {
try {
sleep(timeOne);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.firstCounterFinished();
}
});
sleep(timeTwo);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
mCounterFinishedListener.secondCounterFinished();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void setTimes(long timeOne, long timeTwo){
this.timeOne = timeOne;
this.timeTwo = timeTwo;
}
public void start(OnCounterFinishedListener listener){
mCounterFinishedListener = listener;
t.start();
}
interface OnCounterFinishedListener{
void firstCounterFinished();
void secondCounterFinished();
}
}
Then inside your main thread you can start this counter as
final Counter counter = new Counter(this);
counter.setTimes(5000, 5000);
counter.start(new Counter.OnCounterFinishedListener() {
#Override
public void firstCounterFinished() {
// Update your first TextView
}
#Override
public void secondCounterFinished() {
// Update your second TextView
}
});
I'm writing a android application. I have a CountDownTimer in between my application and i want until the timer to zero, all my app run(user must be select the true Button) and when become zero and the user did'nt anything, the other action performed (the user loses).
this is CountDownTimer :
new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
a.setText("" + millisUntilFinished / 1000);
/*while (millisUntilFinished / 1000 != 1) {
}*/
}
public void onFinish() {
a.setText("done!");
}
}.start();
and this is part of code:
if ((randomAndroidColor1 == rainbow[0]) {
findViewById(ans).setBackgroundColor(rainbow2[0]);
findViewById(ans).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
c3.setBackgroundColor(rainbow1[2]);
}
});
}
How to access to millisUntilFinished variable in above if condition?
Timer and if condition worked correctly but I want to combine them.
If I understood correctly , you can use an instance boolean variable.
boolean isWon = false;
private void countDown() {
isWon=false; // Reset every method call.
// Set listener once in method.
findViewById(R.id.answer).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
isWon=true;
}
});
new CountDownTimer(5000, 1000) {
public void onTick(long millisUntilFinished) {
// onTick works.
}
public void onFinish() {
if(isWon){
// Won
}else{
// Lose
}
}
}.start();
}
My Timer doesn't stop running if I cancel it!
The Timer only stops if I shut down the whole app!
I don't know why the Timer is not cancelled. If I print out every try on cancelling the Timer I get hundrets of lines but the Timer does not stop!
My Class:
public class PlayActivity extends AppCompatActivity
implements View.OnClickListener, SeekBar.OnSeekBarChangeListener, MediaplayerEvent {
//region Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Initialize_Layout();
Initialize_Objects();
}
#Override
protected void onResume() {
super.onResume();
MusicService.setMediaPlayerEvent(this);
txvSongtitle.setText(serviceInterface.MP_getActualSong().getTitle());
Start_Timer();
}
#Override
protected void onPause() {
timer.cancel();
MusicService.clearMediaPlayerEvent();
super.onPause();
}
#Override
public boolean onSupportNavigateUp() {
finish();
return super.onSupportNavigateUp();
}
//endregion
//region Methods
private void Start_Timer() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (serviceInterface.MP_isPlaying()) {
runOnUiThread(new Runnable() {
#Override
public void run() {
seekBar.setMax(serviceInterface.MP_getDuration());
seekBar.setProgress(serviceInterface.MP_getCurrentPosition());
}
});
}
else {
runOnUiThread(new Runnable() {
#Override
public void run() {
timer.cancel();
}
});
}
}
}, 0, 200);
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
serviceInterface.MP_seekTo(progress);
Start_Timer();
}
}
//endregion
}
I hope you can help me!
Thanks!
I would suggest using a Thread instead of a Timer. Your Start_Timer()code would change to something like the following:
private Thread mTimerThread;
...
private void Start_Timer() {
mTimerThread = new Thread() {
#Override
public void run() {
try {
while (!isInterrupted()) {
if (serviceInterface.MP_isPlaying()) {
runOnUiThread(new Runnable() {
#Override
public void run() {
seekBar.setMax(serviceInterface.MP_getDuration());
seekBar.setProgress(serviceInterface.MP_getCurrentPosition());
}
});
} else {
interrupt();
}
Thread.sleep(200);
}
} catch (InterruptedException e) {
}
}
}
mTimerThread.start();
}
Threads are more efficient and lightweight and perfect for your needs. Plus, by setting the Thread to a global variable, you can make sure to call mTimerThread.interrupt(); during Android lifecycle events, such as onPause().
I hope this fixes your issue. Remember, the Java Thread is your friend!
You're creating and starting a new timer the user moves the seekbar (in onProgressChanged()). That also means you lose the reference to the old one. When isPlaying turns false, all the timers will try to cancel timer -- which only references the most recent one.
I ve got this function here:
public void stoprecording()
{
this.recorder.stop();
this.recorder.reset();
this.recorder.release();
}
which stops the recoridng. This is within the class Audio. I also got this function here:
public void recordtimer(final int timer)
{
/*First Part with timer*/
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
CountDownTimer countDowntimer = new CountDownTimer(timer, 100000)
{
public void onTick(long millisUntilFinished) {}
public void onFinish() {
this.stoprecording();
}
};countDowntimer.start();
}
});
thread.start();
this.stoprecording();
}
also within the class Audio. I canĀ“t execute this.stoprecording(); because the class CountDownTimer doesn t have this function. How can I execute this function?
Looking at your code it seems there is no need to call stoprecording() from this, since it does not belong to CountDownTimer class you have defined.
Just call it like
public void onFinish() {
stoprecording();
}
or if you want to definitely use this, follow the #gary111 suggestion thus doing
public void onFinish() {
YourClass.this.stoprecording();
}
I have implemented the timer functionality in android app, I able to finish the timer from other local methods by calling timerObject.cancel() . Its working perfectly.
But when I tried to call same in onTick() method for specific condition, i am not able to cancel the timer, it last till the timer time ends.
How can i cancel the timer?
Looking at the source code for CountDownTimer it is easy to see why it is not working. cancel() merely removes the message for ticking the timer from the queue. But the message handler that gets called at each tick posts a message for the next tick after calling onTick(). So either you have to call cancel() outside of onTick(), via a Handler for example, or switch to using the Timer class instead.
if using RXJava2. this code can help you.
public abstract class CountDownTimer {
private TimeUnit timeUnit;
private Long startValue;
private Disposable disposable;
public CountDownTimer(Long startValue,TimeUnit timeUnit) {
this.timeUnit = timeUnit;
this.startValue = startValue;
}
public abstract void onTick(long tickValue);
public abstract void onFinish();
public void start(){
io.reactivex.Observable.zip(
io.reactivex.Observable.range(0, startValue.intValue()), io.reactivex.Observable.interval(1, timeUnit), (integer, aLong) -> {
Long l = startValue-integer;
return l;
}
).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Long>() {
#Override
public void onSubscribe(Disposable d) {
disposable = d;
}
#Override
public void onNext(Long aLong) {
onTick(aLong);
}
#Override
public void onError(Throwable e) {
e.printStackTrace();
}
#Override
public void onComplete() {
onFinish();
}
});
}
public void cancel(){
if(disposable!=null) disposable.dispose();
}
}
using:
public class MainActivity extends AppCompatActivity {
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start_activity);
new CountDownTimer(10L, TimeUnit.SECONDS) {
#Override
public void onTick(long tickValue) {
Log.d("CountDown", "Remaining: " + tickValue);
// cancel();
}
#Override
public void onFinish() {
Log.d("CountDown", "The End!! ");
}
}.start();
}
}
the owner of the code https://gist.github.com/chemickypes/fa3b7fc5b5a00a3ce37fee5815018702