I want to finish my CountdownTimer on Back button. I know that there a a few similar questions but that doesn´t help me with my problem.
I´ve got the following code in onCreate()
#Override
public void onFinish() {
new CountDownTimer(10000, 550) {
#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));
}
#Override
public void onFinish() {
System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
new CountDownTimer(10000, 350) {
#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));
System.out.println("HHH");
}
#Override
public void onFinish() {
System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
Intent highscore = new Intent (MainActivity.this, Highscore_eintragen.class);
highscore.putExtra("count", count);
startActivity(highscore);
}
}.start();
}
}.start();
}
}.start();
Now what I need is, if the user presses the back button during the CountdownTimer to finish my activity. Any solutions for that problem?
Call CountDownTimer.cancel():
http://developer.android.com/reference/android/os/CountDownTimer.html#cancel()
store reference to current CountDownTimer instance in your activity during creation, to have access to it inside Activity.
Related
I am trying to create a countDownTimer but, whenever I click on the button the app crashes.
I want that if I click on player1 button player2 countdown should pause and vice versa for player2.
The Error I am getting:
Attempt to invoke virtual method 'void
android.os.CountDownTimer.cancel()' on a null object reference
Here is the Code
public class Timer extends AppCompatActivity {
Button player1, player2;
long incrementTime = 3000;
int time;
long timeinLong;
ImageButton pause;
CountDownTimer player1count, player2count;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
player1 = findViewById(R.id.player1);
player2 = findViewById(R.id.player2);
Intent intent = getIntent();
time = intent.getIntExtra("time", 0);
timeinLong = time * 60000;
int minutes = (int) (timeinLong / 1000) / 60;
int seconds = (int) (timeinLong / 1000) % 60;
String timeFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
player1.setText(timeFormatted);
player1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startCountDown(player1);
player2count.cancel();
}
});
player2.setText(timeFormatted);
player2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startCountDown2(player2);
player1count.cancel();
}
});
}
private void startCountDown(final Button button) {
player1count = new CountDownTimer(timeinLong, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeinLong = millisUntilFinished;
updateCountDownText(button);
}
#Override
public void onFinish() {
timeinLong = 0;
updateCountDownText(button);
}
}.start();
}
private void startCountDown2(final Button button) {
player2count = new CountDownTimer(timeinLong, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeinLong = millisUntilFinished;
updateCountDownText(button);
}
#Override
public void onFinish() {
timeinLong = 0;
updateCountDownText(button);
}
}.start();
}
private void updateCountDownText(Button button) {
int minutes = (int) (timeinLong / 1000) / 60;
int seconds = (int) (timeinLong / 1000) % 60;
String timeFormatted = String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
button.setText(timeFormatted);
if (timeinLong < 30000) {
button.setTextColor(Color.RED);
} else {
button.setTextColor(Color.BLACK);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (player1count != null) {
player1count.cancel();
}
}
}
player2count only gets initialized inside startCountDown2, which is only called inside player2.setOnClickListener. Hence, if you click on the player1 button before ever clicking on player2 button, you'll get a NullPointerException, since calling player2count.cancel() on a not-yet-initialized player2count is not allowed. To prevent this from happening, it would be appropriate to just check for null in this case:
if (player2count != null) {
player2count.cancel();
}
Just don't cancel timers unless they're intialized, it will bring NPE, so check if they're not null in both players as below
player1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startCountDown(player1);
if (player2count != null)
player2count.cancel();
}
});
player2.setText(timeFormatted);
player2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startCountDown2(player2);
if (player1count != null)
player1count.cancel();
}
});
you don't initialize that when click listener called
i fixed it for myself by add try catch on .cancel lines
or set
if (player1count != null)
...
my code is given below in that for Each Question there is i.e. when count down ends its jump to next question and count down starts again, i want that when the countdown ends it should jump to the result page..and even after jumping to next question countdown should not stop.
#Override
protected void onResume()
{
super.onResume();
questionPlay = db.getRuleQuestionMode(mode);
totalQuestion = questionPlay.size();
mCountDown = new CountDownTimer(TIMEOUT, INTERVAL) {
#Override
public void onTick(long millisUntilFinished) {
progressBar.setProgress(progressValue);
progressValue++;
}
#Override
public void onFinish() {
mCountDown.cancel();
}
};
showQuestion(index);
db.close();
}
private void showQuestion(final int index) {
if (index < totalQuestion) {
thisQuestion++;
txtQuestion.setText(String.format("%d/%d", thisQuestion, totalQuestion));
progressBar.setProgress(0);
progressValue = 0;
txtView1.setText(questionPlay.get(index).getQus());
btnA.setText(questionPlay.get(index).getAnswerA());
btnB.setText(questionPlay.get(index).getAnswerB());
btnC.setText(questionPlay.get(index).getAnswerC());
btnD.setText(questionPlay.get(index).getAnswerD());
mCountDown.start();
Button btnca =(Button) findViewById(R.id.btnca);
btnca.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
StyleableToast st= new StyleableToast(getApplicationContext(),questionPlay.get(index).getCorrectAnswer(), Toast.LENGTH_SHORT);
st.setBackgroundColor(Color.RED);
st.setTextColor(Color.WHITE);
st.setCornerRadius(3);
st.show();
score-=10;
}
});
} else {
Intent intent = new Intent(this, Done.class);
Bundle dataSend = new Bundle();
dataSend.putInt("SCORE", score);
dataSend.putInt("TOTAL", totalQuestion);
dataSend.putInt("CORRECT", correctAnswer);
intent.putExtras(dataSend);
startActivity(intent);
finish();
}
}
#Override
public void onClick(View v) {
mCountDown.cancel();
if (index < totalQuestion) {
Button clickedButton = (Button) v;
if (clickedButton.getText().equals(questionPlay.get(index).getCorrectAnswer())) {
score += 10; // increase score
correctAnswer++; //increase correct answer
showQuestion(++index);
} else {
vibrator.vibrate(50);
showQuestion(++index); // If choose right , just go to next question
}
txtScore.setText(String.format("%d", score));
//clickedButton.setBackgroundColor(Color.YELLOW);;
}
}
#Override
public void onStop() {
if(mCountDown != null)
mCountDown.cancel();
super.onStop();
}
remove mCountDown.start(); in your showQuestion method.
in your onFinish method, call your results page from there
I'm making a quiz app in which there is a sound game.But i find that sound keeps playing even when app is closed. Two time I'm using mediaplayer.
1.while clicking on image button.
2.on changing question.
Question is changed every 15 sec and after killing app sound is getting played every 15 seconds.
imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mediaPlayer.start();
}
});
btnA.setOnClickListener(this);
btnB.setOnClickListener(this);
btnC.setOnClickListener(this);
btnD.setOnClickListener(this);
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
}
#Override
protected void onResume()
{
super.onResume();
questionPlay = db.getMorseQuestionMode(mode);
totalQuestion = questionPlay.size();
mCountDown = new CountDownTimer(TIMEOUT, INTERVAL) {
#Override
public void onTick(long millisUntilFinished) {
progressBar.setProgress(progressValue);
progressValue++;
}
#Override
public void onFinish() {
mCountDown.cancel();
showQuestion(++index);
}
};
showQuestion(index);
}
private void showQuestion(int index) {
if (index < totalQuestion) {
thisQuestion++;
txtQuestion.setText(String.format("%d/%d", thisQuestion, totalQuestion));
progressBar.setProgress(0);
progressValue = 0;
int QusId = this.getResources().getIdentifier(questionPlay.get(index).getQus().toString(), "raw", getPackageName());
btnA.setText(questionPlay.get(index).getAnswerA());
btnB.setText(questionPlay.get(index).getAnswerB());
btnC.setText(questionPlay.get(index).getAnswerC());
btnD.setText(questionPlay.get(index).getAnswerD());
mCountDown.start();
mediaPlayer= MediaPlayer.create(this,QusId);
mediaPlayer.start();
} else {
Intent intent = new Intent(this, Done.class);
Bundle dataSend = new Bundle();
dataSend.putInt("SCORE", score);
dataSend.putInt("TOTAL", totalQuestion);
dataSend.putInt("CORRECT", correctAnswer);
intent.putExtras(dataSend);
startActivity(intent);
finish();
}
}
#Override
public void onClick(View v) {
mCountDown.cancel();
if (index < totalQuestion) {
Button clickedButton = (Button) v;
if (clickedButton.getText().equals(questionPlay.get(index).getCorrectAnswer())) {
score += 10; // increase score
correctAnswer++; //increase correct answer
showQuestion(++index);
} else {
vibrator.vibrate(50);
showQuestion(++index); // If choose right , just go to next question
}
txtScore.setText(String.format("%d", score));
}
}
//CLicking back Button
public void onBackPressed() {
showExitAlertBox();
}
public void showExitAlertBox() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setMessage("You want to quit the play?");
//Yes Quit then go to category page
alertDialog.setPositiveButton("YES", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int button) {
Intent intent = new Intent(getApplicationContext(), CategorySecond.class);
startActivity(intent);
}
});
//no Quit stay on same page
alertDialog.setNegativeButton("NO", null);
alertDialog.show();
mediaPlayer.stop();
}
}
Error Showing us below
W/MediaPlayer-JNI: MediaPlayer finalized without being released
Cancel your timer and stop mediaplayer if playing in onStop
#Override
public void onStop() {
if (mediaPlayer.isPlaying())
mediaPlayer.stop();
if(mCountDown != null)
mCountDown.cancel();
super.onStop();
}
handle on destroy
#Override
public void onDestroy() {
if (mediaPlayer.isPlaying())
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
if(mCountDown != null)
mCountDown.cancel();
}
You have not released the mediaplayer properly.
Use
protected void onStop(){
mediaPlayer.release();
mediaPlayer = null;
}
call this method where ever required.
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 have the user inputting the time in the countdown timer.
Right now, its fixed to 10sec. How can i change this to user input ?
CountDownTimer counter = new CountDownTimer(10000,1000) {
#Override
public void onTick(long millisUntilFinished) {
//millisUntilFinished=20000;
settime.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
quescount++;
if (quescount%5==0){
round ++;
rndno.setText(String.valueOf(round));
// onBackPressed();
}
quescounter.setText("Out of "+String.valueOf(quescount));
// j = randomcount(getcount(),1);
++qcounter;
//j=qcounter;
if (qcounter<count)
setdata(String.valueOf(list.get(qcounter)));
else
{
Collections.shuffle(list);
qcounter=0;
setdata(String.valueOf(list.get(qcounter)));
}
}
};
Call this method where you take the input from the user:
public void startCountDown(long duration) {
CountDownTimer counter = new CountDownTimer(duration, 1000) {
#Override
public void onTick(long millisUntilFinished) {
//millisUntilFinished=20000;
settime.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
quescount++;
if (quescount%5==0){
round ++;
rndno.setText(String.valueOf(round));
// onBackPressed();
}
quescounter.setText("Out of "+String.valueOf(quescount));
// j = randomcount(getcount(),1);
++qcounter;
//j=qcounter;
if (qcounter<count)
setdata(String.valueOf(list.get(qcounter)));
else
{
Collections.shuffle(list);
qcounter=0;
setdata(String.valueOf(list.get(qcounter)));
}
}
};
}
You'll probably want to make your CountDownTimer variable global as well.