How keep a CountDownTimer running when I press the back button - android

I have a CountDownTimer which updates a TextView, but when I press the back button it stops.
CountDownTimer timer = new CountDownTimer(600000, 100) {
public void onTick(long millisUntilFinished) {
calendar.setTimeInMillis(millisUntilFinished);
cron.setText(sf.format(calendar.getTime()));
}
public void onFinish() {
}
};
How can I keep it running when I press the back button and the activity gets destroyed?
PS: I also start a GPS service when the timer starts, Is there a way to put the CountDownTimer in the service?

If your timer needs to live beyond the lifecycle of your Activity, then it does not belong there. You can certainly place it into a Service, or another object (like a singleton) that can stay resident in memory.

As prashant and Devunwire pointed out, you need to use a Service. Make sure you call startService() before binding to it, this causes the Service to stay alive even if the calling Activity is destroyed.
Make sure as well that the service stops itself with stopSelf() after the timer has finished and did whatever its supposed to do.

I think it should be possible to put the countdown timer in a Service. You can trigger the timer to start by sending an intent to the service. Also, you will have to use some mechanism such as a callback or intent or messenger to relay the update time back to your UI.

Override the back button and then make it behave like the home button. This way your activity is never destroyed. That said, I don't think this is considered "good practice."
To do what I'm saying you just place this into your activity class.
#Override
public void onBackPressed() {
moveTaskToBack(true);
}
Whatever you do, as an optimization, you should make sure that the TextView is not updated if the TextView isn't visible on the screen. This should save battery life and probably prevent the creation of strings which will reduce garbage collections.

Related

Android how to stop timer when app go to background

I know there are ton of questions as this have been asked in stackoverflow. Most of those suggest to implement onResume and onPause to control how the app behaves when it goes to background/foreground. But I couldn't actually use that method in my case.
I have a timer that will run when my application start (or after user login). So it is not dependent on any activity in my app. What I want to do is to stop the timer (to save power resource) when app goes to background and restart it when app come back to foreground. By implementing onResume and onPause will stop and start the timer when user switch between the activities (because I implemented in all the activities), and this is not what I wanted.
Please give advice how this to be done in better way.
You can use cancel() method in onPauso() so when the app are in background you stop the timmer
In the method onResume() you launch other time your Timer.
you can see method in:
http://developer.android.com/reference/java/util/Timer.html
extend the Application class and add a public static counter on it. On every onPause() and OnResume(), increment or decrement it, when the counter is zero you app is in background.

How to handle the termination of an app-wide polling-routine?

I have kind of a tricky situation in my app.
I implemented a mechanism that contacts a remote server every 60 seconds to check if new data is available. If so, the new data is displayed in the app. So far so good.
I implemented the mechanism the following way:
It gets started in the onCreate() method of my MainActivity.
The polling routine gets stopped in my MainActivity's onDestroy() method.
This makes sure the polling is always active as long as the app is running. Also, if I start another Activity from my MainActivity, I also want the polling to run.
My Problem:
When I exit my application via the Back-Button, everything works fine and the polling stops. But when I exit my application through the Home-Button, the polling routine stays alive since onDestroy() of my MainActivity is not called, but I want it to stop.
If I change my code and stop the polling routine in the onPause() method of my MainActivity, I have the problem that the polling also gets stopped when I launch a new Activity.
What I want:
I want the polling to run as long as my Application (not my MainActivity) is in foreground / visible to the user. As soon as the User exits the application by pressing the Home-Button from anywhere in the App, or by pressing the Back-Button from the MainActivity, I want the polling to stop.
ADDITIONAL:
I also do not want to restart and stop the service everytime I switch Activities. Since the user of my Application will switch Activitys very often, this would just be a lot of overhead. Furthermore, I want the "refresh"-cycle to be exactly 60 seconds. I cannot guarantee that when I always restart the service and stop it again. It needs to be started once when the app gets started, and stopped when the app is no longer in foreground.
How to achieve that?
Isn't there some kind of simple way to check when the App is in foreground and when its hidden / closed?
This is my singelton-polling mechanism:
private Timer t;
private static Updater instance;
protected Updater() {
// Exists only to defeat instantiation.
}
public static Updater getInstance() {
if(instance == null) {
instance = new Updater();
}
return instance;
}
public void startPollingRoutine(int interval, int delay) {
t = new Timer();
// Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
update(); // some asynctask that does the updating
}
}, delay, interval);
}
public static void stopPollingRoutine() {
t.cancel();
}
In code:
Updater.getInstance().startPollingRoutine(60000, 0);
Updater.getInstance().stopPollingRoutine();
I think the best way how to handle it is to create some BaseActivity which all activities will extend. And to perform this actions in onResume/onPause. Or you can try using services.
you need to create a service and trigger it in your main class that service will be triggered unless you explicitly stop it on destroy means onBackpressed()/onDetroy() and let it run in onPause() method
Use a singleton, and let it have a counter variable. Increase it when you send intent to start a new activity, and decrease it in the onPause.
Than you can tell if the polling has to stop; when the counter in the singleton is zero.
Thank you all for your help and time.
I finally found a solution by myself that meets all my requirements.
I followed this tutorial to make it work: http://www.mjbshaw.com/2012/12/determining-if-your-android-application.html
The basic Idea is to extend the Application class and keep reference to how many Activitys are "alive" at a certain time.

Should I start/stop service in onStart/onStop, or onCreate/onDestroy

Currently, I have service, which runs in separate process. Here is the code in main activity.
#Override
public void onStart() {
super.onStart();
// Start auto complete service.
autoCompleteServiceIntent = new Intent(AutoCompleteService.class.getName());
startService(autoCompleteServiceIntent);
bindService(autoCompleteServiceIntent, serviceConnection, 0);
}
#Override
public void onStop() {
super.onStop();
// Stop auto complete service.
unbindService(serviceConnection);
stopService(autoCompleteServiceIntent);
autoCompleteServiceIntent = null;
}
The service will have the following characteristics.
The service runs in separate process. The reason is that, it will load a large data into memory. Having the service to run in separate process, will allow us to have larger memory limit.
Once main activity dead, the service shall dead too.
I was wondering, should I start/stop service in onStart/onStop pairs? Or, shall I start/stop service in onCreate/onDestroy.
The good thing I can think of, when having the code in onStart/onStop pairs is that, I can release unused memory immediately, whenever the activity is invisible. Hence, free up large system resource. Note, onDestroy is not always being called immediately, even the activity has quit.
The bad thing is, if I press HOME and come back frequently, my service will perform memory loading/unloading frequently. This may cause my application performs considerable slower.
In your scenario you should stop the service onDestroy the reason been is that, its called when the activity is destroyed self, foreclosed or by system when it needs memory. So that will be a appropriate place to end the service.
Where else onStop will be even called when you move back and forth in your application or visit home. The reason onDestroy is not called on home press is the activity is not destroyed yet. Where as if you close activity pressing back it will call onDestroy.

Android: How to backup a database when the application gets closed?

I am needing help to determine the right approach. I want to make a backup of an internal database to a location in the external storage every time the whole application gets interrupted or terminated/destroyed. I want to call this method from a central class called Main which extends Application. The reason for that is, that I need to use several activites and I want to call the backup Method only when needed (like described when the whole application gets destroyed or interrupted by another application). I try to avoid calling this backup method in every activity in their onPause() methods.
I thought about starting a service in the onCreate() method of the application, and starting the backup method when the service gets destroyed. But this won't help in the case of an interrupt, as far as I understood the logic behind services. And also the service doesn't seem to start. startService(new Intent(getApplicationContext(), BackupService.class)); Furthermore I don't think it is a good approach to just use the onDestroy() method of a service, this is not what the service class is made for in my opinion.
So summarizing my Question, do you know a better way then using a service, or if not do you know how I should use the service to be able to call a backup only at the point when the whole app (and not only an activity) is interrupted or destroyed.
First of all, if your service "doesn't seem to start", you are probably doing something wrong.
To accomplish your goal make a backup of an internal database to a location in the external storage every time the whole application gets interrupted or terminated/destroyed:
There are three cases in general here.
If you want to do it in the activity layer:
To know when your application is crashed, you need to implement a custom handler to catch the uncaught exceptions.
To know when your activity is "interrupted", the only way is do it in onPause.
To know when your activity is "terminated", the only way is to do it in onDestroy.
This will require you to have a clear navigation and only do it in your "main activity", and all the other activity starts and comes back to it OR use a flag to indicate if the pause was caused by going to another activity.
If you want to do it in the service layer: (Your way of doing it onDestroy won't allow you to detect interrupted case since you will have to start service sticky to keep it running)
You will have to set up a flag on each activity onBind (you will have to bind it and unbind it) to know if it is a crash/interrupt/termination, which will complicate other part of your code.
To avoid running repetitive code, you will have to create a generic base class and extend your other activities from it.
I use this approach to play background music in one of my games, but I guess it works in this scenario as well.
Use a boolean flag to indicate whether or not your app is launching another part of your app.
boolean movingInApp = false;
....
movingInApp = true;
Intent intent...
.....
public void onPause() {
if(!movingInApp) {
//start service
}
}
public void onResume() {
movingInApp = false;
//Stop service
}
By setting the value of movingInApp to true before launching any intent etc, you can prevent your app from starting the service. Remember to set it to false again later in your onResume() method. If the system makes your app go to the background, this will be false, and your service will be started.
Why dont u have all of your activities extend a base activity which in turn extend the android activity class
I the base activity have backupDB method in the onPause
Therefore u dont have to put it in every activity pause method

stop or refresh an app's activity

I have a START and STOP button in the main screen of an App. there are some GUI and threads that are instantiated when I click on START. When I click on stop, I want everything to be stopped and the activity should come back to its origin state. To the state that is exactly same like when launched (when we tapped on App icon in mobile).
Is it possible to do this? I tried with finish() , this killed the app and exited . I don't want to exit from main screen. rather, on clicking STOP I want app to come back to origin or born state. Thanks.
How are you running your threads? Are they vanilla threads or subclasses of AsyncTask?
If these are instances of an AsyncTask object, you can use the cancel() method to cancel it and then inside your doInBackground() method, you could check the isCancelled() method to see if it has indeed been canceled, and then exit gracefully.
Pseudo code below:
private YourTask taskRef;
public void btnStartHandler() {
taskRef = new YourTask();
taskRef.execute();
}
public void btnStopHandler() {
taskRef.cancel();
}
and then, in your AsyncTask:
public Void doInBackground(Void... arg0) {
// Background loop start
if (this.isCancelled()) {
return;
}
// Background loop continue...
}
If you're using threads, you can interrupt them and catch the exception and handle it there. Furthermore, you could create a method that you call from onCreate() called initApp() or something that initializes everything. You could also use that initApp() from the STOP button click handler to reset values back to startup defaults.
You can restart the activity with finish() and then call startActivity(getIntent());. This will effectively restart your activity and put it in its default state, no matter how it was started.
Before doing that make sure to cancel all threads or AsyncTasks as TJF suggested (you can and should do this in the onDestroy overload).
For more info about restarting an activity, and a discussion about pros and cons, see this question: Reload activity in Android

Categories

Resources