I have a service with a timer in the background. This timer executes a certain task after 20 seconds pass. I want the same timer to execute another task, but in a different amount of seconds. This would be easy by launching both services at the same time, but I am trying to learn how I can do it this other way.
I tried this, but it isn't showing up:
cdt = new CountDownTimer(20000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Log.v(TAG, /*"Time remaining " +*/ (millisUntilFinished / 1000) + " seconds left");
if(millisUntilFinished / 10000 == 0){ //TEN SECONDS
Log.v(TAG, (millisUntilFinished % 1000) + " seconds left");
}
}
#Override
public void onFinish() {
Log.v(TAG, "Finished");
Now, I should be getting two different log messages at ten seconds. Instead, I only get one. Here is my logCat:
The arrow indicates where there should have been another log message.
I am lost. I would really appreciate any feedback (positive or negative)! Thank you so much for all of your help.
As you said yourself, you could launch both services at the same time.
Or inside the first service, you could pass an Intent with some parameters to inform the new amount of time and then call startService().
Intent it = new Intent(getApplicationContext(), YourService.class);
it.putExtra("Time", timeInMillis);
startService(it);
I mean, modify your Service to get an extra from the calling Intent, something like this:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
long time = intent.getLongExtra("Time",0);
// Do your ticking here, based on that variable.
}
//...
}
Edit: Let's say you want to make your timer run first at 5 seconds, then at 10, 15, and so on.
Once you finish your timer, you could pass the Intent to the new Service/Timer adding the seconds you want. Like:
it.putExtra("Time", timeInMillis + 5000);
Use this type.
cdt = new CountDownTimer(10000, 1000) { //finished on 10 Seconds
#Override
public void onTick(long millisUntilFinished) {
Log.v(TAG, /*"Time remaining " +*/ (millisUntilFinished / 1000) + " seconds left");
}
#Override
public void onFinish() {
Log.v(TAG, "First 10 Seconds Finished");
LoadNextCountdown(); // call the Next Countdown method
}
}
.start();
//Method for Next Countdown
public void LoadNextCountdown()
{
cdt2=new CountDownTimer(10000,1000) { //finished on 10 Seconds
#Override
public void onTick ( long millisUntilFinished){
Log.v(TAG, /*"Time remaining " +*/ (millisUntilFinished / 1000) + " seconds left");
}
#Override
public void onFinish () {
Log.v(TAG, "Next 10 Seconds Finished");
}
} .start();
}
Happy Coding :)
Your log is not displaying because:
if(millisUntilFinished / 10000 == 0){ //TEN SECONDS
Log.v(TAG, (millisUntilFinished % 1000) + " seconds left");
}
you want it to display when you have 10000 millisUntilFinished but 10000/10000 = 1 not 0.
it should be:
if(millisUntilFinished / 10000 == 1) || if(millisUntilFinished % 10000 == 0)
or simply:
if(millisUntilFinished == 10000)
Related
I have developed a workout app. I've two timers on the screen one is for the total timer and one for exercise time also some tts and MediaPlayer sounds. When the screen is locked my exercise timer is stuck after 10 seconds but my total remaining time timer is still running. So confused about why is it happening, I've verified battery optimization permission on\off but the issue is still the same. I've set a toast in tick function and I turn off the screen when I come back toast is showing but my timer is stuck. Can anyone help to get out of this? Thanks in advance. Countdown works fines when the screen is opened or connected to the charger.
Exercise Timer code below...
excerciseCountDownTimer = new CountDownTimer(seconds * 1000, 1000) {
public void onTick(long millisUntilFinished) {
totalExcerciseSec = (int) (millisUntilFinished / 1000);
int currentMinute = totalExcerciseSec / 60;
int currentSecond = totalExcerciseSec % 60;
binding.workoutTimeTv.setText(String.format("%02d", currentMinute) + ":" + String.format("%02d", currentSecond));
if (totalExcerciseSec == 0) {
totalRemaingCountDownTimer.cancel();
onExerciseCompleteActions();
}
}
public void onFinish() {
}
}.start();
Total Remaining Timer code below...
totalRemaingCountDownTimer = new CountDownTimer(seconds * 1000, 1000) {
public void onTick(long millisUntilFinished) {
totalRemainingSecs = (int) (millisUntilFinished / 1000);
int minutes = totalRemainingSecs / 60;
int second = totalRemainingSecs % 60;
timerPlaying = true;
binding.totalRemainingTimeTv.setText(String.format("%02d", minutes) + ":" + String.format("%02d", second));
}
public void onFinish() {
}
}.start();
Your activity is getting stopped or destroyed and that's why your timer gets stuck.
To keep the timer running even if the app is closed or killed, see this way:-
You can use this technique to detect how long the user was inactive (even when the app is in the background).
Create a SharedPreference & its Editor object. Then declare 3 long variables such:
mMillisUntilFinished = pref.getLong("millisUntilFinished",60*1000); // Replace with your time
long userExitedMillis = pref.getLong("userExitedMillis",0);
long timeLeft = mMillisUntilFinished - (System.currentTimeMillis() - userExitedMillis);
Pass timeLeft as millisInFuture. Inside timer, assign millisUntilFinished to a public variable in every tick
new CountDownTimer(timeLeft,1000){
#Override
public void onTick(long millisUntilFinished) {
Log.d("TAG", "Time left : " + millisUntilFinished/1000 + " sec");
mMillisUntilFinished = millisUntilFinished;
}
#Override
public void onFinish() {
// Timer completed
}
}.start();
Save this mMillisUntilFinished variable & current time in shared preference at onStop().
#Override
protected void onStop() {
super.onStop();
editor.putLong("millisUntilFinished",mMillisUntilFinished);
editor.putLong("userExitedMillis",System.currentTimeMillis());
editor.apply();
}
Tip : If you subtract userExitedMillis from System.currentTimeMillis() then you will get the activity inactive time (in mili second).
I have used this class to solve my issue according to my requirements.
https://gist.github.com/Gautier/737759
I can set only minutes on my countdown using edit text, how about it can set also seconds on edit text on the countdown timer, any help guys don't have any clue how to set seconds
public void onClick(View v) {
switch (v.getId()) {
case R.id.startTimer:
//If CountDownTimer is null then start timer
if (countDownTimer == null) {
String getMinutes = minutes.getText().toString();//Get minutes from edittexf
//Check validation over edittext
if (!getMinutes.equals("") && getMinutes.length() > 0) {
int noOfMinutes = Integer.parseInt(getMinutes) * 60 * 1000;//Convert minutes into milliseconds
startTimer(noOfMinutes);//start countdown
startTimer.setText(getString(R.string.stop_timer));//Change Text
} else
Toast.makeText(MainActivity.this, "Please enter no. of Minutes.", Toast.LENGTH_SHORT).show();//Display toast if edittext is empty
} else {
//Else stop timer and change text
stopCountdown();
startTimer.setText(getString(R.string.start_timer));
}
break;
case R.id.resetTimer:
stopCountdown();//stop count down
startTimer.setText(getString(R.string.start_timer));//Change text to Start Timer
countdownTimerText.setText(getString(R.string.timer));//Change Timer text
break;
}
}
You can try this to show minutes and seconds:
new CountDownTimer(90000, 1000) {
#Override
public void onTick(long millisUntilFinished) {
String text = String.format(Locale.getDefault(), "Time Remaining %02d min: %02d sec",
TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) % 60,
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) % 60);
tvTime.setText(text);
}
});
Change the initialization of countDownTimer according to your needs
IMO, startTimer accepts milliseconds as its parameters. You cannot set the Timer in seconds there. But use this to show seconds:
startTimer.setText(Integer.parseInt(getString(R.string.stop_timer)) / 1000);
This shows the timer in Seconds.
Hope it helps.
Hello i am creating a timer in my app but i stuck in getting seconds left in day end from now (12.00 AM) my timer basically need to show time left for today 11-59 PM. I successfully created a timer function which takes inputs in seconds and then start countdown but i am unable to calculate remaining time of today in seconds
Below is my timer function
time = 30;
// Here i need time left for today end for example current time is 11.55 then remaining time is 5 minutes in seconds (300)
public void startTimer() {
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
textTimer.setText("0:"+checkDigit(time));
time--;
}
public void onFinish() {
textTimer.setText("try again");
}
}.start();
}
public String checkDigit(int number) {
return number <= 9 ? "0" + number : String.valueOf(number);
}
remaining time of today in seconds:
Calendar tomorrow = Calendar.getInstance();// creating a calendar for tomorrow at 12am
tomorrow.add(Calendar.DAY_OF_YEAR, 1);
tomorrow.set(Calendar.HOUR_OF_DAY, 0);
tomorrow.set(Calendar.MINUTE, 0);
tomorrow.set(Calendar.SECOND, 0);
tomorrow.set(Calendar.MILLISECOND, 0);
remainingSeconds = ( tomorrow.getTimeInMillis() - System.currentTimeMillis() ) / 1000
public void reverseTimer(int Seconds,final TextView tv,final Button button,final TextView txt2){
final CountDownTimer CountDownTimer1 = new CountDownTimer(Seconds* 1000+1000, 1000) {
public void onTick(long millisUntilFinished) {
int seconds = (int) (millisUntilFinished / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
tv.setText("Time : " + String.valueOf(minutes)
+ ":" + String.valueOf(seconds));
}
public void onFinish() {
if(score > highscore)
sethighscore(txt2);
tv.setText("Completed");
Reset(tv,button,txt2);
}
}.start();
}
I have a reset button that set's the 'clicked' to true and a Reset function that is called when the reset button is pressed or when the timer finishes, I tried adding the following condition to the 'OnTick':
if(clicked == true)
{
CountDownTimer1.cancel();
}
But I get the error that it may not have been initialised I know what it means I just don't understand where to initialise it and how? or is there a different way I can stop it outside of this function?
You are creating an abstract subclass of CountDownTimer. All the code in onTick and onFinish belong to that that object.
Inside those methods, you can reference the object with this. So you can simply do:
this.cancel();
Or even just:
cancel();
I am trying to create a countdown timer that runs even when the app is killed or when the phone is turned off. For example, let's say I run my countdown timer to count down from 5 hours. When I turned it off it resets to zero. I want it so that when I start counting it down from 5 hours and turn my phone for one hour and turn it back on, the timer shows four hours as the time remaining. I am looking into services and multithreading but haven't been able to produce or find a solution that will work for me.
In Android i want to run countdown timer who can run in background also
Implementing a Count down timer using Service in the background
Here is my code segment:
start_timer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new AlertDialog.Builder( MainActivity.this )
.setMessage( "Are you sure you want to block the selected apps for the set amount of time?" )
.setPositiveButton( "Yeah man!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d( "AlertDialog", "Positive" );
hourint = Integer.valueOf(number_text.getText().toString());
minuteint = Integer.valueOf(minute_text.getText().toString());
secondint = Integer.valueOf(second_text.getText().toString());
Log.i("YourActivity", "Hours: " + hourint);
Log.i("YourActivity", "Minutes: " + minuteint);
Log.i("YourActivity", "Seconds: " + secondint);
totalTimeCountInMilliseconds = ((hourint*60*60) +(minuteint*60) + (secondint)) * 1000; // time count
timeBlinkInMilliseconds = 30*1000;
countDownTimer = new CountDownTimer(totalTimeCountInMilliseconds, 500) {
// 500 means, onTick function will be called at every 500 milliseconds
#Override
public void onTick(long leftTimeInMilliseconds) {
long seconds = leftTimeInMilliseconds / 1000;
mSeekArc.setVisibility(View.INVISIBLE);
start_timer.setVisibility(View.INVISIBLE);
block_button1.setVisibility(View.INVISIBLE);
if ( leftTimeInMilliseconds < timeBlinkInMilliseconds ) {
// textViewShowTime.setTextAppearance(getApplicationContext(), R.style.blinkText);
// change the style of the textview .. giving a red alert style
if ( blink ) {
number_text.setVisibility(View.VISIBLE);
minute_text.setVisibility(View.VISIBLE);
second_text.setVisibility(View.VISIBLE);
// if blink is true, textview will be visible
} else {
number_text.setVisibility(View.INVISIBLE);
minute_text.setVisibility(View.INVISIBLE);
second_text.setVisibility(View.INVISIBLE);
}
blink = !blink; // toggle the value of blink
}
second_text.setText(String.format("%02d", seconds % 60));
minute_text.setText(String.format("%02d", (seconds / 60) % 60));
number_text.setText(String.format("%02d", seconds / 3600)); // format the textview to show the easily readable format
}
#Override
public void onFinish() {
// this function will be called when the timecount is finished
//textViewShowTime.setText("Time up!");
number_text.setVisibility(View.VISIBLE);
minute_text.setVisibility(View.VISIBLE);
second_text.setVisibility(View.VISIBLE);
mSeekArc.setVisibility(View.VISIBLE);
start_timer.setVisibility(View.VISIBLE);
block_button1.setVisibility(View.VISIBLE);
}
}.start();
}
})
.setNegativeButton( "Nope!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d( "AlertDialog", "Negative" );
dialog.cancel();
}
} )
.show();
How can I achieve this and what modifications do I have to make to my code?
EDIT: HERE IS MY FULL CODE:
http://pastebin.com/pth9KZWP
EDIT 2: HERE IS REVISED CODE:
My app cannot start. And I don't receive any logcat statements so I am not sure what to do...
http://pastebin.com/L8HgGtsy
After the countdown time is entered, calculate when the countdown will end and write that to persistent storage. Then any time the app starts back up, read that time and calculate how much time is left from now.
I figured it out to anyone having the same problem ;)
Here is retrieving the SharedPreferences at the top of the class in onCreate
startimerPreferences = getPreferences(MODE_APPEND);
Date startDate = new Date(startimerPreferences.getLong("time", 0));
timerstarted = startDate.getTime();
Log.e("This is the start time!!!!!: ", timerstarted + "");
endTimerPreferences = getPreferences(MODE_APPEND);
Date endDate = new Date(endTimerPreferences.getLong("time", 0));
timerends = endDate.getTime();
Log.e("This is the end time!!!!!: ", timerends + "");
Date openagain = new Date(System.currentTimeMillis());
reopened = openagain.getTime();
Here if there is still time remaining start the timer with that time remaining:
if(timerstarted > 0)
{
if(reopened <timerends){
//start countdown timer with new time.
//set countdowntime to timerends-reopen.
newtotalTimeCountInMilliseconds = timerends-reopened;
countDownTimer = new CountDownTimer(newtotalTimeCountInMilliseconds, 500) {
// 500 means, onTick function will be called at every 500 milliseconds
#Override
public void onTick(long leftTimeInMilliseconds) {
long seconds = leftTimeInMilliseconds / 1000;
mSeekArc.setVisibility(View.INVISIBLE);
start_timer.setVisibility(View.INVISIBLE);
block_button1.setVisibility(View.INVISIBLE);
if (leftTimeInMilliseconds < timeBlinkInMilliseconds) {
// textViewShowTime.setTextAppearance(getApplicationContext(), R.style.blinkText);
// change the style of the textview .. giving a red alert style
if (blink) {
number_text.setVisibility(View.VISIBLE);
minute_text.setVisibility(View.VISIBLE);
second_text.setVisibility(View.VISIBLE);
// if blink is true, textview will be visible
} else {
number_text.setVisibility(View.INVISIBLE);
minute_text.setVisibility(View.INVISIBLE);
second_text.setVisibility(View.INVISIBLE);
}
blink = !blink; // toggle the value of blink
}
second_text.setText(String.format("%02d", seconds % 60));
minute_text.setText(String.format("%02d", (seconds / 60) % 60));
number_text.setText(String.format("%02d", seconds / 3600)); // format the textview to show the easily readable format
}
#Override
public void onFinish() {
// this function will be called when the timecount is finished
//textViewShowTime.setText("Time up!");
number_text.setVisibility(View.VISIBLE);
minute_text.setVisibility(View.VISIBLE);
second_text.setVisibility(View.VISIBLE);
mSeekArc.setVisibility(View.VISIBLE);
start_timer.setVisibility(View.VISIBLE);
block_button1.setVisibility(View.VISIBLE);
}
}.start();
}
}
Here is the initial timer with the user submitting the action. I have the current time and end time committed and saved in SharedPreferences.
start_timer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new AlertDialog.Builder( MainActivity.this )
.setMessage( "Are you sure you want to block the selected apps for the set amount of time?" )
.setPositiveButton("Yeah man!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d("AlertDialog", "Positive");
hourint = Integer.valueOf(number_text.getText().toString());
minuteint = Integer.valueOf(minute_text.getText().toString());
secondint = Integer.valueOf(second_text.getText().toString());
Log.i("YourActivity", "Hours: " + hourint);
Log.i("YourActivity", "Minutes: " + minuteint);
Log.i("YourActivity", "Seconds: " + secondint);
Date currenttime = new Date(System.currentTimeMillis());
timerstarted = currenttime.getTime();
Log.e("This is the current time: ", timerstarted + "");
startimerPreferences = getPreferences(MODE_APPEND);
SharedPreferences.Editor starteditor = startimerPreferences.edit();
starteditor.putLong("time", timerstarted);
starteditor.commit();
Date endtime = new Date(System.currentTimeMillis());
timerends = endtime.getTime() + (((hourint * 60 * 60) + (minuteint * 60) + (secondint)) * 1000);
Log.e("This is the end time: ", timerends + "");
endTimerPreferences = getPreferences(MODE_APPEND);
SharedPreferences.Editor endeditor = endTimerPreferences.edit();
endeditor.putLong("time", timerends);
endeditor.commit();
totalTimeCountInMilliseconds = (((hourint * 60 * 60) + (minuteint * 60) + (secondint)) * 1000); // time count
timeBlinkInMilliseconds = 30 * 1000;
countDownTimer = new CountDownTimer(totalTimeCountInMilliseconds, 500) {
// 500 means, onTick function will be called at every 500 milliseconds
#Override
public void onTick(long leftTimeInMilliseconds) {
long seconds = leftTimeInMilliseconds / 1000;
mSeekArc.setVisibility(View.INVISIBLE);
start_timer.setVisibility(View.INVISIBLE);
block_button1.setVisibility(View.INVISIBLE);
if (leftTimeInMilliseconds < timeBlinkInMilliseconds) {
// textViewShowTime.setTextAppearance(getApplicationContext(), R.style.blinkText);
// change the style of the textview .. giving a red alert style
if (blink) {
number_text.setVisibility(View.VISIBLE);
minute_text.setVisibility(View.VISIBLE);
second_text.setVisibility(View.VISIBLE);
// if blink is true, textview will be visible
} else {
number_text.setVisibility(View.INVISIBLE);
minute_text.setVisibility(View.INVISIBLE);
second_text.setVisibility(View.INVISIBLE);
}
blink = !blink; // toggle the value of blink
}
second_text.setText(String.format("%02d", seconds % 60));
minute_text.setText(String.format("%02d", (seconds / 60) % 60));
number_text.setText(String.format("%02d", seconds / 3600)); // format the textview to show the easily readable format
}
#Override
public void onFinish() {
// this function will be called when the timecount is finished
//textViewShowTime.setText("Time up!");
number_text.setVisibility(View.VISIBLE);
minute_text.setVisibility(View.VISIBLE);
second_text.setVisibility(View.VISIBLE);
mSeekArc.setVisibility(View.VISIBLE);
start_timer.setVisibility(View.VISIBLE);
block_button1.setVisibility(View.VISIBLE);
}
}.start();
}
})
.setNegativeButton("Nope!", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d("AlertDialog", "Negative");
dialog.cancel();
}
})
.show();