Keep Timer Ticking in Background - android

How can I keep the value of my timer resuming after going to another activity , my problem is that it's set to default if I switched to another activity I thought of using sharedpreference but it won't help because I need it to keep decrementing in the background.
public void reset()
{
countDownTimer.cancel();
}
private void setTimer() {
int time = 5;
if(countDownTimer==null)
{
totalTimeCountInMilliseconds = 60 * time * 1000;
}
else
{
reset();
totalTimeCountInMilliseconds = 60 * time * 1000;
}
}
private void startTimer() {
countDownTimer = new CountDownTimer(totalTimeCountInMilliseconds, 500) {
// 500 means, onTick function will be called at every 500
// milliseconds
//#Override
public void onTick(long leftTimeInMilliseconds) {
seconds = leftTimeInMilliseconds / 1000;
textViewShowTime.setText(String.format("%02d", seconds / 60)
+ ":" + String.format("%02d", seconds % 60));
// 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!");
textViewShowTime.setVisibility(View.VISIBLE);
}
}.start();
}

You should stop your CountDownTimer in onPause and restart in onResume, your textViewShowTime might not be valid while your activity is in background.
If you need to call some code every 500ms no matter what activity you are in, then consider using AlarmManager.

Related

countDowntimer not Resetting for a new Value and shows the old value always

I am trying to show a countDownTimer in my activity. the value I am using in the countDowntimer is coming from a recyclerview of another activity using bundle. when I click one of the recyclerview time for the first time, the countDownTimer shows the time running perfectly. but when I select another time, the old instance continues to run. I have implemented the cancel and onFinish() methods to but they are not working as I want. I searched everywhere but everyone suggested about cancel and onFinish() methods. I am unable to find a solution now.
public void getData() {
if(countDownTimer!=null){
countDownTimer.cancel();
}
if (replaceTime != null) {
time = Integer.parseInt(replaceTime);
} else
Toast.makeText(FullTimerActivity.this, "",
Toast.LENGTH_LONG).show();
totalTimeCountInMilliseconds = time;
timeBlinkInMilliseconds = 30 * 1000;
countDownTimer = new CountDownTimer(totalTimeCountInMilliseconds, 500) {
#Override
public void onTick(long leftTimeInMilliseconds) {
long seconds = leftTimeInMilliseconds / 1000;
if (leftTimeInMilliseconds < timeBlinkInMilliseconds) {
if (blink) {
// mTextField.setVisibility(View.VISIBLE);
// if blink is true, textview will be visible
} else {
// mTextField.setVisibility(View.INVISIBLE);
}
blink = !blink;
}
String a = String.format("%02d", seconds / 60) + ":" + String.format("%02d", seconds % 60);
textView.setText(a);
}
#Override
public void onFinish() {
Toast.makeText(FullTimerActivity.this, "Finished", Toast.LENGTH_SHORT).show();
}
}.start();
}
thank you in advance.
In onFinish() also set the text to TextView like below
textView.setText("0");

how do i add miliseconds option in this code?

I am learning android. I made this stopwatch app work from my reference book.It only shows Hour:minutes:seconds but I want to add milliseconds right to the seconds.how do I do that.
code::-
public class StopWatchActivity extends AppCompatActivity {
int seconds;
boolean running;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stop_watch);
runTimer();
}
public void startTimer(View view){
running = true;
}
public void stopTimer(View view){
running = false;
}
public void resetTimer(View view){
running = true;
seconds = 0;
}
public void runTimer(){
final TextView textView = (TextView) findViewById(R.id.timer);
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
int hours = seconds / 3600;
int minutes = (seconds % 3600) / 60;
int sec = seconds % 60;
String time = String.format("%d:%02d:%02d", hours,
minutes,sec);
textView.setText(time);
if(running) {
seconds++;
}
handler.postDelayed(this, 1000);
}
});
}
}
The first step would be to change the field seconds to milliSeconds because you want to keep track of that TimeUnit.
When restarting your handler with handler.postDelayed(this, 1000); define 1 millisecond as delay instead of 1000 (= 1 Second) like this handler.postDelayed(this, 1); then you just need to adjust your calculations and you are done :-)
An easier solution would be:
Instead of saving the elapsed seconds in your activity, save the time that the timer started (e.g. startTime)
Then, in your handler's runnable, get the current time and subtract the start time to find the elapsed time.
Pseudocode:
long startTimeNanos
public void runTimer() {
startTime = new Date()
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
long currentTime = System.nanoTime()
long elapsedNanos = currentTime - startTimeNanos
// calculate seconds and millis
// and set the textview text
handler.postDelayed(this, 1000);
}
});
}
This way, you can change the time that the handler fires and it won't affect anything else.

Cannot get pause and resume functionality to work with progress bar

I am trying to create a timer with a circle progress bar. I have found a good example to begin with http://www.androidtutorialshub.com/android-count-down-timer-tutorial/. This example has the looks that I need but I want to add pause and resume functionality to it. So, I do have the pause and resume working, however after I click "Pause" and then "Resume" the progress bar starts from scratch for a spit of a second and then resumes from the position pause was set on(which is the goal). My guess is that the progress bar is set to 100% somewhere and then replaced with pause position, but I cant find the part where that might happen.
Modified mainActivity code:
public class MainActivity extends AppCompatActivity {
private long timeCountInMilliSeconds = 1 * 60000;
long startTime;
long difference;
long difference1;
private enum TimerStatus {
STARTED,
STOPPED,
}
private TimerStatus timerStatus = TimerStatus.STOPPED;
private ProgressBar progressBarCircle;
private EditText editTextMinute;
private TextView textViewTime;
private ImageView imageViewReset;
private ImageView imageViewStartStop;
private CountDownTimer countDownTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBarCircle = (ProgressBar) findViewById(R.id.progressBarCircle);
editTextMinute = (EditText) findViewById(R.id.editTextMinute);
textViewTime = (TextView) findViewById(R.id.textViewTime);
imageViewReset = (ImageView) findViewById(R.id.imageViewReset);
imageViewStartStop = (ImageView) findViewById(R.id.imageViewStartStop);
imageViewReset.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
reset();
}
});
imageViewStartStop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pauseResume();
}
});
}
private void reset() {
stopCountDownTimer();
restartCountDownTimer();
}
private void pauseResume() {
if (timerStatus == TimerStatus.STOPPED) {
timeCountInMilliSeconds = 1 * 50000;
// setProgressBarValues(timeCountInMilliSeconds);
progressBarCircle.setMax((int) (timeCountInMilliSeconds) / 1000);
progressBarCircle.setProgress((int) (timeCountInMilliSeconds) / 1000);
imageViewReset.setVisibility(View.VISIBLE);
imageViewStartStop.setImageResource(R.drawable.icon_stop);
editTextMinute.setEnabled(false);
timerStatus = TimerStatus.STARTED;
startCountDownTimer();
startTime = System.currentTimeMillis();
} else {
imageViewReset.setVisibility(View.GONE);
imageViewStartStop.setImageResource(R.drawable.icon_start);
editTextMinute.setEnabled(true);
timerStatus = TimerStatus.STOPPED;
stopCountDownTimer();
if(difference == 0) {
difference = System.currentTimeMillis() - startTime;
}
else{
difference1 = System.currentTimeMillis() - startTime;
difference += difference1;}
}
}
private void startCountDownTimer() {
countDownTimer = new CountDownTimer(timeCountInMilliSeconds - difference, 1000) {
#Override
public void onTick(long millisUntilFinished) {
textViewTime.setText(hmsTimeFormatter(millisUntilFinished));
progressBarCircle.setProgress((int) (millisUntilFinished / 1000));
}
#Override
public void onFinish() {
textViewTime.setText(hmsTimeFormatter(timeCountInMilliSeconds - difference));
// setProgressBarValues(timeCountInMilliSeconds - difference);
progressBarCircle.setMax((int) (timeCountInMilliSeconds - difference) / 1000);
progressBarCircle.setProgress((int) (timeCountInMilliSeconds - difference) / 1000);
imageViewReset.setVisibility(View.GONE);
imageViewStartStop.setImageResource(R.drawable.icon_start);
editTextMinute.setEnabled(true);
timerStatus = TimerStatus.STOPPED;
}
}.start();
countDownTimer.start();
}
private void restartCountDownTimer() {
difference = 0;
difference1 = 0;
countDownTimer = new CountDownTimer(timeCountInMilliSeconds, 1000) {
#Override
public void onTick(long millisUntilFinished) {
textViewTime.setText(hmsTimeFormatter(millisUntilFinished));
progressBarCircle.setProgress((int) (millisUntilFinished / 1000));
}
#Override
public void onFinish() {
textViewTime.setText(hmsTimeFormatter(timeCountInMilliSeconds));
// setProgressBarValues(timeCountInMilliSeconds);
progressBarCircle.setMax((int) (timeCountInMilliSeconds) / 1000);
progressBarCircle.setProgress((int) (timeCountInMilliSeconds) / 1000);
imageViewReset.setVisibility(View.GONE);
imageViewStartStop.setImageResource(R.drawable.icon_start);
editTextMinute.setEnabled(true);
timerStatus = TimerStatus.STOPPED;
}
}.start();
countDownTimer.start();
}
private void stopCountDownTimer() {
countDownTimer.cancel();
}
private String hmsTimeFormatter(long milliSeconds) {
String hms = String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(milliSeconds),
TimeUnit.MILLISECONDS.toMinutes(milliSeconds) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milliSeconds)),
TimeUnit.MILLISECONDS.toSeconds(milliSeconds) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliSeconds)));
return hms;
}
}
The XML file is the same as in the link provided above(the link to the sample code).
Any help would be very much appreciated.
Probably the error is in your pauseResume. There you say progressBarCircle.setProgress((int) (timeCountInMilliSeconds) / 1000);. This sets the current progress to the specified value. In your case this means the same value as you max value. I think you should move the whole block up into the onCreate method.
timeCountInMilliSeconds = 1 * 50000;
progressBarCircle.setMax((int) (timeCountInMilliSeconds) / 1000);
progressBarCircle.setProgress((int) (timeCountInMilliSeconds) / 1000);
It should be enough to initialize these values once at the beginning.
[Edit]
The behavior seems good to me. Let's say you press pause if the timer is at 47sec, now depends on your timing, the timer can be paused at 999 milliseconds or 001 msec. (to point edge cases). In the first case you have to wait "nearly" one second, to be precise 999 msec., until the timer switches visibly the state. In the seconds case it feels like the app responds directly, because you only have to wait 001 msec. If you want to fix that, normalize your difference value like so:
private void pauseResume() {
if (timerStatus == TimerStatus.STOPPED) {
...
} else {
...
difference += (((int) (System.currentTimeMillis() - startTime) / 1000) + 1) * 1000;
}
}
I also removed the usless difference1 variable.
Another improvement I made, I've removed the if else statement, because it is also useless.
You can also remove the + 1 to always wait 1sec. before you see something visual.

Restart countodown timer with different timer android

I am making a repeating countdown timer app.I require the countdown timer to restart with a different time.I am using a global variable in the constructor of the countdown timer.But the problem is that it always restarts from the starting of the first given interval.
public void chance(final int tota, final int cur, final int exercise,int pass,int flag)
{
Log.i("inside value","reached");
a = new CountDownTimer((tempmilliseconds) * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
tempmilliseconds = (int) millisUntilFinished / 1000;
Log.i("inside value",Integer.toString(tempmilliseconds));
updatetimer(millisUntilFinished);
}
#Override
public void onFinish() {
mtext.setText("0:00");
cancel();
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
currentcompleted++;
if (on == 0) {
on = 1;
int exercis = MainActivity.restmint * 60 + MainActivity.restsec;
tempmilliseconds=exercis;
chance(tota, curr + 1, exercis, 0, 0);
} else {
on = 0;
int exercis = MainActivity.exermint * 60 + MainActivity.exersec;
tempmilliseconds=exercis;
chance(tota, curr + 1, exercis, 0, 0);
}
}
}, 1000);
}
};
a.start();
}
Below is the code for resume operations:
public void resume(View view) {
Button mytext=(Button) findViewById(R.id.resume);
if( mytext.getText().toString()=="Pause") {
mytext.setText("Play");
a.cancel();
}
else {
mytext.setText("Pause");
Log.i("Value of temp",Integer.toString(tempmilliseconds));
a.start();
}
}
The timer is stopping but when started in the resume function restarts with the original time and not specified by tempmilliseconds.Note tempmilliseconds is updated every seconds.
Any help/snippets/suggestions is appreciated.Thank you!
A CountDownTimer will not allow itself to be disturbed in any case. It will remember the time it was born with till someone kills it.
If you look at its documentation you'd see that it directly inherits from Object class and has only four methods: start(), cancel(), onFinish() (abstract) and onTick() (abstract). Thats pretty much it. So, you basically are left with no choice but to call cancel() and then re-initialise the timer. Or, you can extend the CountDownTimer class and encapsulate this under the hood.
In either case the cost of cancelling ad re-initialising may get tedious.

how to measure the time taken by activities in android

I am working on quiz type application and I want to calculate the time between some activities. for example, my level starts from activity A and ends at activity H. I want to calculate the time taken by all the activities. Can anyone please help me to count the time taken from the first activity to the ending activity?
Declare the variables
//counter of time since app started, a background task
private long mStartTime = 0L;
private TextView mTimeLabel;
//handler to handle the message to the timer task
private Handler mHandler = new Handler();
Start the timer in onCreate or onStart or your own method (click of button)
if(mStartTime==0L){
mStartTime=SystemClock.uptimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask,100);
}
timer function
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
final long start = mStartTime;
long millis = SystemClock.uptimeMillis() - start;
int seconds = (int) (millis / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
mTimeLabel.setText("" + minutes + ":"
+ String.format("%02d", seconds));
mHandler.postDelayed(this, 200);
}
};
when the app is minimized, pause the timer
#Override
protected void onPause() {
mHandler.removeCallbacks(mUpdateTimeTask);
super.onPause();
}
when the app is resumed, resume the timer
#Override
protected void onResume() {
super.onResume();
mHandler.postDelayed(mUpdateTimeTask, 100);
}

Categories

Resources