My timer app is crashing as soon as countDownTimer.cancel() method is called
it is showing null object reference even though I have done it correctly, I can't find the problem.
Please, someone, take a look on the code below : (also I am attaching logcat)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual
method 'void android.os.CountDownTimer.cancel()' on a null object
reference
package com.example.rajdeepkgautam.itimer;
import android.media.MediaPlayer;
import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int max = 600;
int start = 30;
TextView timerTextView;
SeekBar timerSeekBar;
boolean timerActive = false;
Button runButton;
CountDownTimer countDownTimer;
public void resetTimer() {
timerTextView.setText("0:30");
timerSeekBar.setProgress(start);
timerSeekBar.setEnabled(true);
countDownTimer.cancel();
runButton.setText("RUN!");
timerActive = false;
}
public void buttonClicked(View view) {
if(timerActive) {
resetTimer();
} else {
timerActive = true;
runButton.setText("STOP!");
timerSeekBar.setEnabled(false);
CountDownTimer countDownTimer = new CountDownTimer((timerSeekBar.getProgress()*1000) + 100, 1000) {
#Override
public void onTick(long l) {
TimerUpdate((int) l/1000);
}
#Override
public void onFinish() {
MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.horn);
mediaPlayer.start();
resetTimer();
}
}.start();
}
}
public void TimerUpdate(int TimeLeft) {
int minutes = TimeLeft/60;
int seconds = TimeLeft - (minutes*60);
if(seconds <=9) {
timerTextView.setText(Integer.toString(minutes) + ":" + "0" + Integer.toString(seconds));
} else {
timerTextView.setText(Integer.toString(minutes) + ":" + Integer.toString(seconds));
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timerSeekBar = findViewById(R.id.timerSeekBar);
timerTextView = findViewById(R.id.timerTextView);
runButton = findViewById(R.id.runButton);
timerSeekBar.setMax(max);
timerSeekBar.setProgress(start);
timerSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
TimerUpdate(i);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
It's because of not initializing the countDownTimer. You are creating a local variable and never assigning the instantiated CountDownTimer to the countDownTimer of MainActivity.
Change the line:
CountDownTimer countDownTimer = new CountDownTimer((timerSeekBar.getProgress()*1000) + 100, 1000)
to:
countDownTimer = new CountDownTimer((timerSeekBar.getProgress()*1000) + 100, 1000)
Related
This question already has answers here:
How do I pass data between Activities in Android application?
(53 answers)
Closed 1 year ago.
I am creating a Pomodoro Timer app. It has 2 activities:
The first one is the home page.
Second is for setting a time.
I want to make a third activity with recent times
I want to create a third activity that takes the input times from the second activity and stores them in a list, but I don't know how to transfer the input-data from the second activity to the third ?
Activity 1:
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button newTime = findViewById(R.id.newTime);
Button currentTime = findViewById(R.id.currentTime);
Button recents = findViewById(R.id.recentTime);
newTime.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent activity2Intent = new Intent(getApplicationContext(), Activity2.class);
startActivity(activity2Intent);
overridePendingTransition(R.anim.slide_in_right,R.anim.slide_out_left);
}
});
// currentTime.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View v) {
// Intent currentActivityIntent = new Intent(getApplicationContext(), currentActivity.class);
// startActivity(currentActivityIntent);
// overridePendingTransition(R.anim.slide_in_right,R.anim.slide_out_left);
// }
// });
}
}
Activity 2:
package com.example.pomotimer;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import java.util.Locale;
public class Activity2 extends AppCompatActivity {
private TextView TextViewCountdown;
private Button Button_Start_Pause;
private Button Reset;
private Button buttonSet;
private Button select_Time;
private EditText edit_Text_Input;
private CountDownTimer countDownTimer;
public long mStartTimeinMillis;
private long timeLeft = mStartTimeinMillis;
private boolean timerRunning;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
TextViewCountdown = findViewById(R.id.textViewCount);
Button_Start_Pause = findViewById(R.id.bnStartPause);
Reset = findViewById(R.id.reset);
select_Time = findViewById(R.id.selectTime);
edit_Text_Input = findViewById(R.id.edit_Text_Input);
buttonSet = findViewById(R.id.buttonSet);
select_Time.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
edit_Text_Input.setVisibility(View.VISIBLE);
buttonSet.setVisibility(View.VISIBLE);
buttonSet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String input = edit_Text_Input.getText().toString();
if (input.length() == 0){
Toast.makeText(Activity2.this, "Field can't be empty", Toast.LENGTH_SHORT).show();
return;
}
long millisInput = Long.parseLong(input)*60000;
if (millisInput == 0){
Toast.makeText(Activity2.this, "Timer cannot be set to 0", Toast.LENGTH_SHORT).show();
return;
}
setTime(millisInput);
edit_Text_Input.setText("");
// Intent res = new Intent(getApplicationContext(), currentActivity.class);
// startActivityForResult(res, (int) millisInput, null);
}
});
}
});
Button_Start_Pause.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (timerRunning){
pauseTimer();
}
else{
startTimer();
}
}
});
Reset.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
resetTimer();
}
});
int minutes = (int) (timeLeft/1000)/60;
int seconds = (int) (timeLeft/1000)%60;
String timeLeftFormatted = String.format(Locale.getDefault(),"%02d:%02d", minutes, seconds);
TextViewCountdown.setText(timeLeftFormatted);
}
#Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
}
public void setTime(long milliseconds){
mStartTimeinMillis = milliseconds;
resetTimer();
}
private void startTimer(){
countDownTimer = new CountDownTimer(timeLeft,1000) {
#Override
public void onTick(long millisUntilFinished) {
// The countdown timer has an automatic method of reducing time by 1s
timeLeft = millisUntilFinished;
int minutes = (int) (timeLeft/1000)/60;
int seconds = (int) (timeLeft/1000)%60;
String timeLeftFormatted = String.format(Locale.getDefault(),"%02d:%02d", minutes, seconds);
TextViewCountdown.setText(timeLeftFormatted);
}
#Override
public void onFinish() {
timerRunning = false;
Button_Start_Pause.setText("Start");
Button_Start_Pause.setVisibility(View.INVISIBLE);
}
}.start();
timerRunning = true;
Button_Start_Pause.setText("pause");
}
private void pauseTimer(){
countDownTimer.cancel();
timerRunning = false;
Button_Start_Pause.setText("Start");
}
private void resetTimer(){
timeLeft = mStartTimeinMillis;
int minutes = (int) (timeLeft/1000)/60;
int seconds = (int) (timeLeft/1000)%60;
Button_Start_Pause.setVisibility(View.VISIBLE);
String timeLeftFormatted = String.format(Locale.getDefault(),"%02d:%02d", minutes, seconds);
TextViewCountdown.setText(timeLeftFormatted);
}
#Override
protected void onStop() {
super.onStop();
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putLong("millisleft", timeLeft);
editor.putBoolean("timerRunning", timerRunning);
editor.apply();
}
#Override
protected void onStart() {
super.onStart();
SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
timeLeft = prefs.getLong("millisleft",mStartTimeinMillis);
timerRunning = prefs.getBoolean("timeRunning", false);
int minutes = (int) (timeLeft/1000)/60;
int seconds = (int) (timeLeft/1000)%60;
String timeLeftFormatted = String.format(Locale.getDefault(),"%02d:%02d", minutes, seconds);
TextViewCountdown.setText(timeLeftFormatted);
}
}
We can pass data to another activity using Intent.
Like before startActivity we need to do:
intent.putExtra("Data", data);
and in thirdActivity onCreate we need to do
intent.getStringExtra("Data");
Inside Activity2
You can place data inside the Intent directly or you can put them in a Bundle and then put the inside the Intent. Avoid using both for consistency.
Intent activity3Intent = new Intent(getApplicationContext(), Activity3.class);
//Direct Intent approach
activity3Intent.putExtras("YOUR_STRING_KEY","YOUR_DATA");
//OR Bundle approach
Bundle bundle = new Bundle();
bundle.putString("YOUR_STRING_KEY","YOUR_DATA");
activity3Intent.putExtras(bundle);
startActivity(activity3Intent);
Inside the Activity3 class.
//if direct intent approach
String value = getIntent.getStringExtra("YOUR_STRING_KEY")
//If bundle approach was used.
String value = getIntent().getExtras().getString("YOUR_STRING_KEY");
I am creating a trivia app. I want the right/wrong animation to occur immediately after the user clicks an answer, and then after 3 seconds, the question to switch automatically(fading into the next question). I tried doing this using Thread.sleep(3000), but the whole program freezes. This is my code so far:
binding.buttonTrue.setOnClickListener(view -> {
checkAnswer(true);
updateQuestion();
//these two calls invoke right/wrong animation
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
changeTheQuestion();
//this invokes fade animation
});
How can I add a period of time between these two animations? Thanks!
Full code:
package com.bawp.trivia;
import android.graphics.Color;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import com.bawp.trivia.data.Repository;
import com.bawp.trivia.databinding.ActivityMainBinding;
import com.bawp.trivia.model.Question;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.List;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
public class MainActivity extends AppCompatActivity {
List<Question> questionList;
Handler mHandler;
private ActivityMainBinding binding;
private int currentQuestionIndex = 0;
SoundPool soundPool;
private int sound1, sound2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
questionList = new Repository().getQuestions(questionArrayList -> {
binding.questionTextview.setText(questionArrayList.get(currentQuestionIndex)
.getAnswer());
updateCounter(questionArrayList);
}
);
mHandler = new Handler();
binding.buttonNext.setOnClickListener(view -> {
currentQuestionIndex = (currentQuestionIndex + 1) % questionList.size();
updateQuestion();
});
binding.buttonTrue.setOnClickListener(view -> {
checkAnswer(true);
updateQuestion();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
changeTheQuestion();
}
}, 3000);
});
binding.buttonFalse.setOnClickListener(view -> {
checkAnswer(true);
updateQuestion();
new Handler().postDelayed(new Runnable() {
public void run() {
changeTheQuestion();
}
}, 3000);
});
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
soundPool = new SoundPool.Builder()
.setMaxStreams(4)
.setAudioAttributes(audioAttributes)
.build();
sound1 = soundPool.load(this, R.raw.correct, 1);
sound2 = soundPool.load(this, R.raw.wrong, 1);
}
private void checkAnswer(boolean userChoseCorrect) {
boolean answer = questionList.get(currentQuestionIndex).isAnswerTrue();
int snackMessageId = 0;
if (userChoseCorrect == answer) {
snackMessageId = R.string.correct_answer;
fadeAnimation();
soundPool.play(sound1, 1, 1, 0, 0, 1);
} else {
snackMessageId = R.string.incorrect;
shakeAnimation();
soundPool.play(sound2, 1, 1, 0, 0, 1);
}
Snackbar.make(binding.cardView, snackMessageId, Snackbar.LENGTH_SHORT)
.show();
}
private void updateCounter(ArrayList<Question> questionArrayList) {
binding.textViewOutOf.setText(String.format(getString(R.string.text_formatted),
currentQuestionIndex, questionArrayList.size()));
}
private void fadeAnimation() {
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
alphaAnimation.setDuration(300);
alphaAnimation.setRepeatCount(1);
alphaAnimation.setRepeatMode(Animation.REVERSE);
binding.cardView.setAnimation(alphaAnimation);
alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
binding.questionTextview.setTextColor(Color.GREEN);
}
#Override
public void onAnimationEnd(Animation animation) {
binding.questionTextview.setTextColor(Color.WHITE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
private void changeTheQuestion() {
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
alphaAnimation.setDuration(300);
alphaAnimation.setRepeatCount(1);
alphaAnimation.setRepeatMode(Animation.REVERSE);
binding.cardView.setAnimation(alphaAnimation);
alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
binding.questionTextview.setTextColor(Color.BLUE);
}
#Override
public void onAnimationEnd(Animation animation) {
currentQuestionIndex = (currentQuestionIndex + 1) % questionList.size();
updateQuestion();
binding.questionTextview.setTextColor(Color.WHITE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
private void updateQuestion() {
String question = questionList.get(currentQuestionIndex).getAnswer();
binding.questionTextview.setText(question);
updateCounter((ArrayList<Question>) questionList);
}
private void shakeAnimation() {
Animation shake = AnimationUtils.loadAnimation(MainActivity.this,
R.anim.shake_animation);
binding.cardView.setAnimation(shake);
shake.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
binding.questionTextview.setTextColor(Color.RED);
}
#Override
public void onAnimationEnd(Animation animation) {
binding.questionTextview.setTextColor(Color.WHITE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
}
Repository.java:
package com.bawp.trivia.data;
import android.util.Log;
import com.android.volley.Request;
import com.android.volley.toolbox.JsonArrayRequest;
import com.bawp.trivia.controller.AppController;
import com.bawp.trivia.model.Question;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
public class Repository {
ArrayList<Question> questionArrayList = new ArrayList<>();
String url = "https://raw.githubusercontent.com/curiousily/simple-quiz/master/script/statements-data.json";
public List<Question> getQuestions( final AnswerListAsyncResponse callBack) {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET,
url, null, response -> {
for (int i = 0; i < response.length(); i++) {
try {
Question question = new Question(response.getJSONArray(i).get(0).toString(),
response.getJSONArray(i).getBoolean(1));
//Add questions to arraylist/list
questionArrayList.add(question);
//Log.d("Hello", "getQuestions: " + questionArrayList);
} catch (JSONException e) {
e.printStackTrace();
}
}
if (null != callBack) callBack.processFinished(questionArrayList);
}, error -> {
});
AppController.getInstance().addToRequestQueue(jsonArrayRequest);
return questionArrayList;
}
}
You cannot call Thread.sleep() on the main (UI) thread. This will freeze your app and cause your app to crash with ANR (Application Not Responsive) error.
You can just post a Runnable that will run a chunk of code after a certain period of time. Something like this:
new Handler().postDelayed(new Runnable() {
public void run() {
changeTheQuestion();
}
}, 3000);
I want to show the progress of the music played in the seekbar. I am not able to do so. Please help!
I am not understanding what's the problem here. I am very much new to programming. I am actually trying to build an app that can play music and the music progress is displayed on the seekbar
package com.example.musicapp;
import androidx.appcompat.app.AppCompatActivity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
MediaPlayer startmusic;
SeekBar seekBar;
ImageButton play;
ImageButton pause;
Handler handler;
Runnable runnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play=findViewById(R.id.play_button);
seekBar=findViewById(R.id.seekBar);
pause=findViewById(R.id.pause_button);
startmusic=MediaPlayer.create(this,R.raw.music);
}
public void playmusic(View v){
startmusic.start();
play.setImageResource(R.drawable.pause);
play.setVisibility(play.GONE);
pause.setVisibility(pause.VISIBLE);
seekBar.setMax(startmusic.getDuration());
Toast toast=Toast.makeText(getApplicationContext(),"Music is playing", Toast.LENGTH_SHORT);
toast.show();
changeSeekbar();
}
private void changeSeekbar() {
if(startmusic.isPlaying()){
seekBar.setProgress(startmusic.getCurrentPosition());
runnable=new Runnable() {
#Override
public void run() {
changeSeekbar();
handler.postDelayed(runnable,100);
}
};
}
}
public void pausemusic(View v){
if(startmusic.isPlaying()) {
startmusic.pause();
play.setImageResource(R.drawable.pause);
play.setVisibility(play.VISIBLE);
pause.setVisibility(pause.GONE);
seekBar.setProgress(startmusic.getCurrentPosition());
Toast toast=Toast.makeText(getApplicationContext(),"Music is paused", Toast.LENGTH_SHORT);
toast.show();
}
}
}
You can use the common methods of the MediaPlayer class in order to show the progress:
start()
stop()
release() – To prevent memory leaks.
seekTo(position) – This will be used with the SeekBar
isPlaying() – Let us know whether the song is being played or not.
getDuration() – Is used to get the total duration. Using this we’ll
know the upper limit of our SeekBar. This function returns the
duration in milli seconds
setDataSource(FileDescriptor fd) – This is used to set the file to be played.
setVolume(float leftVolume, float rightVolume) – This is used to set
the volume level. The value is a float between 0 or 1.
<SeekBar
android:id="#+id/seekbar"
android:layout_margin="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" />
The code for the MainActivity.java class is given below:
public class MainActivity extends AppCompatActivity implements Runnable {
MediaPlayer startmusic;
SeekBar seekBar;
ImageButton play;
ImageButton pause;
Handler handler;
Runnable runnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
play=findViewById(R.id.play_button);
seekBar=findViewById(R.id.seekBar);
pause=findViewById(R.id.pause_button);
startmusic=MediaPlayer.create(this,R.raw.music);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
seekBarHint.setVisibility(View.VISIBLE);
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
seekBarHint.setVisibility(View.VISIBLE);
int x = (int) Math.ceil(progress / 1000f);
if (x == 0 && startmusic != null && !startmusic.isPlaying()) {
clearMediaPlayer();
MainActivity.this.seekBar.setProgress(0);
}
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (startmusic != null && startmusic.isPlaying()) {
startmusic.seekTo(seekBar.getProgress());
}
}
});
}
//its look that you call this method form layout itself
//change your play method defination to
public void playmusic(View v) {
try {
play.setImageResource(R.drawable.pause);
play.setVisibility(play.GONE);
pause.setVisibility(pause.VISIBLE);
Toast toast=Toast.makeText(getApplicationContext(),"Music is playing", Toast.LENGTH_SHORT);
toast.show();
if (startmusic == null) {
startmusic = new MediaPlayer();
}
AssetFileDescriptor afd = context.getResources().openRawResourceFd(/*your raw id resource*/);
if (afd == null)
return;
startmusic.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
startmusic.prepare();
startmusic.setVolume(0.5f, 0.5f);
startmusic.setLooping(false);
seekBar.setMax(startmusic.getDuration());
startmusic.start();
new Thread(this).start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void pausemusic(View v) {
//add null check
if(startmusic != null && startmusic.isPlaying()) {
startmusic.pause();
play.setImageResource(R.drawable.pause);
play.setVisibility(play.VISIBLE);
pause.setVisibility(pause.GONE);
seekBar.setProgress(startmusic.getCurrentPosition());
Toast toast=Toast.makeText(getApplicationContext(),"Music is paused", Toast.LENGTH_SHORT);
toast.show();
}
}
public void run() {
int currentPosition = startmusic.getCurrentPosition();
int total = startmusic.getDuration();
if (currentPosition == total) {
clearMediaPlayer();
}
while (startmusic != null && startmusic.isPlaying() && currentPosition < total) {
try {
Thread.sleep(1000);
currentPosition = startmusic.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
seekBar.setProgress(currentPosition);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
clearMediaPlayer();
}
private void clearMediaPlayer() {
startmusic.stop();
startmusic.release();
startmusic = null;
}
}
I am trying to make the countdown app from the movie Countdown. I am very new to coding.
The goal here is to update the textview that shows the number of seconds left to live.
Here is the java code I wrote to try to accomplish that. I know that the other aspects such as years, days, hours and minutes aren't finished yet.
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity {
private TextView mTextViewCountDownYears;
private TextView mTextViewCountDownDays;
private TextView mTextViewCountDownHours;
private TextView mTextViewCountDownMinutes;
private TextView mTextViewCountDownSeconds;
private Button mButtonAccept;
private CountDownTimer mCountDownTimer;
private Boolean mTimerRunning;
long timeLeftToLive = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar deathDay = Calendar.getInstance();
deathDay.set(2021,7,24,10,14,45);
Calendar today = Calendar.getInstance();
long diff = deathDay.getTimeInMillis() - today.getTimeInMillis();
timeLeftToLive = diff;
mTextViewCountDownYears = findViewById(R.id.text_view_countdown_years);
mTextViewCountDownDays = findViewById(R.id.text_view_countdown_days);
mTextViewCountDownHours = findViewById(R.id.text_view_countdown_hours);
mTextViewCountDownMinutes = findViewById(R.id.text_view_countdown_minutes);
mTextViewCountDownSeconds = findViewById(R.id.text_view_countdown_seconds);
mButtonAccept = findViewById(R.id.button_accept);
mButtonAccept.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startTimer();
}
});
}
private void startTimer(){
mCountDownTimer = new CountDownTimer(timeLeftToLive, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeLeftToLive = millisUntilFinished;
updateTextView();
}
#Override
public void onFinish() {
}
};
}
private void updateTextView() {
long secondsLeft = timeLeftToLive / 1000;
String secondsLeftFormatted = String.format("%02d",secondsLeft);
mTextViewCountDownSeconds.setText(secondsLeftFormatted);
}
}
Your code looks good and you are so close to it working properly! You simply need to add a .start() to the end of your definition of CountDownTimer inside your startTimer() function (before the semi-colon).
Like this:
private void startTimer(){
mCountDownTimer = new CountDownTimer(timeLeftToLive, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeLeftToLive = millisUntilFinished;
updateTextView();
}
#Override
public void onFinish() {
}
}.start();
}
There's a great example for you to reference here if you need it
I want to display a TextView during 10 seconds, then make it disappear, every 5 minutes, but I am not able to do it, I have already read this Android CountDownTimer - adding time results in multiple timers running, and many others, but still cant do it, here is what I have tried
private void placeFingerPrint() {
authViewModel.getSession().compose(bindToLifecycle()).subscribe(session -> {
this.session = session;
TextView textView = view.findViewById(R.id.player_finger_print);
MediaItem mediaItem = getPlayingMediaItem();
new CountDownTimer(20000, 10000) {
#Override
public void onTick(long millisUntilFinished) {
if (fingerprint.getChannel() != null && fingerprint.getChannel().contains(mediaItem.getExternalId())) {
textView.setVisibility(View.VISIBLE);
textView.setText(session.getHouseHoldId());
} else {
textView.setVisibility(View.GONE);
}
}
#Override
public void onFinish() {
textView.setVisibility(View.GONE);
start();
}
}.start();
});
We can achieve this using Thread in android. CountDownTimer usually uses if you have a definite end time.
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class ThreadSample extends AppCompatActivity {
Handler uiHandler = new Handler();
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_thread_sample);
textView = findViewById(R.id.textView);
NameCounter runnable = new NameCounter();
new Thread(runnable).start();
}
class NameCounter implements Runnable {
int count = 0;
boolean show = true;
#Override
public void run() {
while (true) { // add your customized condition here to exit from the loop.
uiHandler.post(new Runnable() {
#Override
public void run() {
if (show)
textView.setVisibility(View.VISIBLE);
else
textView.setVisibility(View.GONE);
}
});
try {
if (show) {
Thread.sleep(10000);
show = false;
} else {
Thread.sleep(5000);
show = true;
}
} catch (Exception e) {
Log.e("ERROR", e.getMessage());
}
}
}
}
}