Saving countTimer() on interrupts (Android) - android

I am creating a game and I put a timer to onCreate method to display time to user and make an action when it reaches to 0. My way works correctly but since I wrote it to onCreate the time continues to count down and if I rotate screen etc it resets the timer seconds. I know why this happens but I could not find a way to stop it when app is paused and make it continue from where it left of when application continues. Here is my code
new CountDownTimer(15000, 1000) {
public void onTick(long millisUntilFinished) {
question.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
question.setText("done!");
Intent i2 = new Intent(getApplicationContext(), CategoryActivity.class);
startActivity(i2);
}
}.start();
Should I save milisUntilFinished to savedInstanceState and make the timer start depending on the savedInstanceState or is there an easier solution
Edit: So I updated my code to reflect the thing I ve asked. This way I can save the last state of timer when the phone is rotated, but timer still does not stop when I open the menu (pause the application.)
if(savedInstanceState!=null){
seconds = savedInstanceState.getInt("seconds");
new CountDownTimer(seconds * 1000, 1000) {
public void onTick(long millisUntilFinished) {
seconds = (int) millisUntilFinished;
question.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
question.setText("done!");
Intent i2 = new Intent(getApplicationContext(), CategoryActivity.class);
startActivity(i2);
}
}.start();
}else {
new CountDownTimer(15000, 1000) {
public void onTick(long millisUntilFinished) {
seconds = (int) millisUntilFinished;
question.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
question.setText("done!");
Intent i2 = new Intent(getApplicationContext(), CategoryActivity.class);
startActivity(i2);
}
}.start();
}

CounDwonTimer mCountTimer;
int seconds = 0;
then just cancel the mCountTimer in onPause and start in `onResme'
protected void onResume(){
super.onReusme();
mCountTimer = new CountDownTimer(seconds*1000,1000){
//......record the seconds
}
}
protected void onPause(){
if(mCountTimer != null)
mCountTimer.cancel();
}
if your activity will destory when rotate the screen,you need onSaveInstanceState.otherwise you do not need this method

I hope the following code will help you,
private long startTime = 0L;
private boolean threadStop = false;
private Handler myHandler = new Handler();
private Runnable updateTimerMethod = new Runnable() {
public void run() {
if (isAdded()) {
timeInMillies = SystemClock.uptimeMillis() - startTime;
//finalTime = timeSwap + timeInMillies;
time.setText(miliSecondToMinSec(timeInMillies));
if (!threadStop)
myHandler.postDelayed(this, 1000);
}
}
};
#Override
public void onStart() {
super.onStart();
if (threadStop) {
threadStop = false;
startTime = SystemClock.uptimeMillis() - timeInMillies;
myHandler.postDelayed(updateTimerMethod, 0);
}
}
#Override
public void onStop() {
threadStop = true;
super.onStop();
}

Related

When the countdowntimer finished i will go next activity?

I have two activity set countdown timer in MainActivity, I want when countdown timer finished it will go next activity.but it's not going to next activity its show timer.
here is my code:
public class MainActivity extends AppCompatActivity {
TextView txtViewDays,txtViewHours,txtViewMinutes,txtViewSecond;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtViewDays = findViewById(R.id.days);
txtViewHours = findViewById(R.id.hours);
txtViewMinutes = findViewById(R.id.minutes);
txtViewSecond = findViewById(R.id.seconds);
start_countdown_timer();
}
private void start_countdown_timer()
{
SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yyyy, HH:mm:ss");
formatter.setLenient(false);
final long[] startTime = new long[1];
String endTime = "23.06.2019, 22:56:10";
long milliseconds=0;
final CountDownTimer mCountDownTimer;
Date endDate;
try {
endDate = formatter.parse(endTime);
milliseconds = endDate.getTime();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
startTime[0] = System.currentTimeMillis();
mCountDownTimer = new CountDownTimer(milliseconds, 1000) {
#Override
public void onTick(long millisUntilFinished) {
Long serverUptimeSeconds =
(millisUntilFinished - startTime[0]) / 1000;
String daysLeft = String.format("%d", serverUptimeSeconds / 86400);
txtViewDays.setText(daysLeft);
String hoursLeft = String.format("%d", (serverUptimeSeconds % 86400) / 3600);
txtViewHours.setText(hoursLeft);
String minutesLeft = String.format("%d", ((serverUptimeSeconds % 86400) % 3600) / 60);
txtViewMinutes.setText(minutesLeft);
Log.d("minutesLeft",minutesLeft);
String secondsLeft = String.format("%d", ((serverUptimeSeconds % 86400) % 3600) % 60);
txtViewSecond.setText(secondsLeft);
}
#Override
public void onFinish() {
Intent i = new Intent(MainActivity.this,New.class);
startActivity(i);
finish();
}
};
mCountDownTimer.start();
}
}
What can I do?
N.B : code is collected and I also try but I can't.Thank you
With your code you need 1561330519961ms that means several days must pass in order for onFinish method to be called. I tried your code with 1min for the timer instead
milliseconds = endDate.getTime();
and worked just fine. After the timer finished it changed activity.
---edit---
This sample code will run for 6 seconds and then call the onFinish method
milliseconds = 6000
mCountDownTimer = new CountDownTimer(milliseconds, 1000) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
Intent i = new Intent(MainActivity.this,Myclass.class);
startActivity(i);
finish();
}
};
mCountDownTimer.start();

Android CountDownTimer and Runnable

what I'm trying to do:
My app connects with a Bluetooth accelerometer and gets acceleration data every 50ms. I want to check for these with a Runnable. And this worked fine. However, for the complete app I added two CountDownTimers:
1) introTimer(), which runs in an AlertDialog and counts down from 3. OnFinish() calls (i) my Runnable, that deals with new acceleration data and (ii) a second timer called
2) mainTimer(), which counts down from 20 and refreshes a TextView on the UI.
My problem is, that my Runnable is only executed once when it is first called. Why is that? Apparently I have not yet understood the threading principles behind this. My next step (probably going to be complicated) is to refresh ImageViews every 50ms (or maybe less often, but still with a relatively high frequency) on the UI, depending on the accelerometer data.
I have thought about deleting the Runnable and putting my calculations in the CountDownTimer, but this might be difficult or inaccurate with the timing/frequency/periods. What do you think?
Here are the code parts. If you think other parts are relevant, I can post them as well:
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
LayoutInflater layoutInflater = getActivity().getLayoutInflater();
View promptView = layoutInflater.inflate(R.layout.intro_timer_prompt, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final TextView introTimer = (TextView) promptView.findViewById(R.id.introTimer);
builder.setView(promptView);
AlertDialog alertD = builder.create();
alertD.show();
introTimer(introTimer, alertD);
}
private void introTimer(final TextView introTimer, final AlertDialog alertD) {
new CountDownTimer(4*1000, 1000) {
public void onTick(long millisUntilFinished) {
introTimer.setText( ""+ (millisUntilFinished / 1000));
}
public void onFinish() {
alertD.cancel();
// mainTimer();
clearArrayLists();
mHandler = new Handler();
mHandlerTask.run();
mainTimer();
}
}.start();
}
private void mainTimer() {
new CountDownTimer((int)DURATION*1000, 10) {
public void onTick(long millisUntilFinished) {
//mTimerView.setText("seconds remaining: " + millisUntilFinished / 1000 + ":" + millisUntilFinished / 1000. );
long millisecs = Math.round(millisUntilFinished % 1000 / 100);
mTimerView.setText("seconds remaining: " + millisUntilFinished / 1000 + ":" + millisecs );
}
public void onFinish() {
String energy = new DecimalFormat("#.##").format(accumulatedKineticEnergy.get(accumulatedKineticEnergy.size()-1));
mTimerView.setText("Accumulated Energy is " + energy + " Joule.");
}
}.start();
}
Runnable mHandlerTask = new Runnable() {
#Override
public void run() {
Log.i(TAG, "executed only once :( ");
if (a_x.size() < DURATION/INTERVAL) {
try {
calcAccList();
//...calc things...;
mHandler.postDelayed(this, (long) (1000*INTERVAL));
} catch (Exception e) {
e.getMessage();
}
}
else {
mHandler.removeCallbacks(mHandlerTask);
}
}
};
A countdown timer doesn't repeat itself when it expires, but you need to start it again. Maybe you can use the AlarmManager in this case to have a better design.

Why does my app crash after hitting Reset

The timer works fine for starting then reseting and leaving the view, but if I start the time then leave the view and return and just hit Reset the app crashes. I know that most people would not hit reset when the timer is not started, but for idiot proofing I need a fix for this any suggestions?
public void startTimer(View view) {
final Handler handler = new Handler();
Timer ourtimer = new Timer();
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
int sec = n % 60;
int min = n / 60;
TextView timer = (TextView) findViewById(R.id.androidtimer);
timer.setText("" + String.format("%02d", min) + ":"
+ String.format("%02d", sec));
// timer.setText(n + " Seconds");
n++;
}
});
}
};
ourtimer.schedule(timerTask, 0, 1000);
}
public void stopTimer(View view) {
timerTask.cancel();
TextView timer = (TextView) findViewById(R.id.androidtimer);
timer.setText("--:--");
timerTask = null;
n = 0;
}
I think your problem is that timerTask is null as long as you do not start the timer.
So a simple if clause might help. If that's not the problem please post the exception.
public void stopTimer(View view) {
if(timerTask != null) {
timerTask.cancel();
}
TextView timer = (TextView) findViewById(R.id.androidtimer);
timer.setText("--:--");
timerTask = null;
n = 0;
}

Countdown timer not looping

Basically I am doing a cardio feature and have three countdown timers in a row nested within each other, so when one timer finishes, the next one starts. One for preparation time, one for workout time and one for rest time, the user chooses the times of these.
I need it to loop however many times the user selects from a numberpicker, but no matter what I do it only goes through it once and doesn't loop so I know it all works it's just the looping part that doesn't work.
Am I missing something here? Is there a better way to do this?
//Main countdown timers loop
for(int i = 0; i <= times.getValue() + 1; i++) //times NumberPicker
{
prepCountTimer = new CountDownTimer(_finalPrep * 1000, 1000) {
public void onTick(long millisUntilFinished) {
tvRoundCount.setText("Round " + roundCount + " / " + times.getValue());
tvCountDown.setText((millisUntilFinished / 1000) + "s");
if(millisUntilFinished <= (6 * 1000))
{
tvCountDown.setTextColor(Color.RED);
}
}
public void onFinish() {
workoutCountTimer = new CountDownTimer(_finalWorkout * 1000, 1000) {
public void onTick(long millisUntilFinished) {
tvCountDown.setTextColor(Color.GREEN);
tvCountDown.setText((millisUntilFinished / 1000) + "s");
if(millisUntilFinished <= 6 * 1000)
{
tvCountDown.setTextColor(Color.RED);
}
}
public void onFinish() {
restCountTimer = new CountDownTimer(_finalRest * 1000, 1000) {
public void onTick(long millisUntilFinished) {
tvCountDown.setTextColor(Color.GREEN);
tvCountDown.setText((millisUntilFinished / 1000) + "s");
if(millisUntilFinished <= 6 * 1000)
{
tvCountDown.setTextColor(Color.RED);
}
}
public void onFinish() {
roundCount = roundCount + 1;
}
}.start();
}
}.start();
}
}.start();
}
the issue here is that you create prepCountTimer and assign on finish ect, then start it. then it reaches the end of for each and loops again making another preopCountTimer and starting it. you need to make your restCountTimer start the next preopCountTimer once it's done. unless I'm understanding something wrong here.
public void callingMethod() {
timerMethod(times.getValue());
// execution continues as your timer will run in a different thread
}
public void timerMethod(final int count) {
if (count == 0) {
// we have done the number of timers we want we can
// call whatever we wanted to once our timers were done
}
//you could use count to get the times for each timer here
startTimer(_finalPrep, new timerListner() {
#Override
public void timerFinish() {
//when timer 1 finishes we will start timer 2
startTimer(_finalWorkout, new timerListner() {
#Override
public void timerFinish() {
//when timer 2 finishes we will start timer 3
startTimer(_finalRest, new timerListner() {
#Override
public void timerFinish() {
//when timer 3 finishes we want to call the next timer in the list.
timerMethod(count - 1);
}
});
}
});
}
});
}
private interface timerListner {
void timerFinish();
}
public void startTimer(int timerTime, final timerListner onFinish) {
// you can pass in other parameters unqiue to each timer to this method aswell
CountDownTimer timer = new CountDownTimer(timerTime * 1000, 1000) {
public void onTick(long millisUntilFinished) {
tvRoundCount.setText("Round " + roundCount + " / " + times.getValue());
tvCountDown.setText((millisUntilFinished / 1000) + "s");
if (millisUntilFinished <= (6 * 1000)) {
tvCountDown.setTextColor(Color.RED);
}
}
#Override
public void onFinish() {
onFinish.timerFinish();
}
};
timer.start();
}

Adding countdowntime to system time

A bit confusing this one but should make sense.
Thanks to all your help I have my app now showing a custom digital clock and a countdowntimer (02:30:00 countdown) running under it.
How do I add 02:30:00 to the current time so a new clock field shows the current time + the countdown?
Thanks
Dj
This is my digitalclock code where would i put the offset to ad 2 hours 30 mins to time...
#Override
protected void onStart() {
super.onStart();
timer = new Timer("DigitalClock");
Calendar calendar = Calendar.getInstance();
final Runnable updateTask = new Runnable() {
public void run() {
countdown.setText(getCurrentTimeString());
}
};
int msec = 999 - calendar.get(Calendar.MILLISECOND);
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(updateTask);
}
}, msec, 1000);
}
#Override
protected void onStop() {
super.onStop();
timer.cancel();
timer.purge();
timer = null;
}
private String getCurrentTimeString() {
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int minute = calendar.get(Calendar.MINUTE);
// int second = calendar.get(Calendar.SECOND);
return String.format("%02d:%02d", hour, minute);
}
Now that I understand your question :p, I think the only way to do that is to reimplement a DigitalClock. Take its source code and play with it by adding an offset to the hours and minutes.
UPDATE:
What I would do is take that code and change this part:
mTicker = new Runnable() {
public void run() {
if (mTickerStopped) return;
mCalendar.setTimeInMillis(System.currentTimeMillis());
setText(DateFormat.format(mFormat, mCalendar));
invalidate();
long now = SystemClock.uptimeMillis();
long next = now + (1000 - now % 1000);
mHandler.postAtTime(mTicker, next);
}
};
mTicker.run();
Convert 2:30:00 to milliseconds and add it to now :
long now = SystemClock.uptimeMillis() + offset;

Categories

Resources