I have a timer running in my activity. Let's say user switches to another activity. Should i pause my timer in that case' because sometimes my whole activity gets killed when i resume my application?
Hold your timer remaining time/value/etc into a global static object. When you switch back, use it for your timer or design a good application lifecycle with onPause, onResume etc.
Related
How i should implement a countdown timer if i need the following usage:
User starts activity A;
In activity A he starts the timer;
User leaves activity A, timer runs in background;
User comes back to activity A;
User see current (updated) values of the timer;
I tried to use a Countdown Timer but it fails at step 5 - after returning to ativity A i cant see values in TextView (in LogCat i do) and system starts another timer (this way, every activity re-open starts one more timer). Should I use service instead or ... show me the way, please.
You can't be sure that after you leave your activity it will be still alive. System could kill it at any time.
The solutions for this use case could be:
Start timer in foreground Service. Such types of services have better chances to be alive.
When you leave your activity you could save last timer value and last timestamp and restore timer with this info after activity is recreated.
PS. If you also want to fire the alarm when timer is finished you should use AlarmManager but keep in mind restrictions from android 6+ (M).
My end goal is this:
MainActivity has a button that starts SubActivity (which is essentially a timer).
Each time the button is pressed a new SubActivity starts.
MainActivity also has a RecyclerView that displays a card for each SubActivity so that you may return to any timer that you have already started.
My problem is I don't know how to return to each Activity. I already did some research, and most people point towards onSaveInstanceState, but from my understanding that simply would recreate the activity by saving values and restoring them. I know my timer SubActivities still proceed in the background because even when I leave the SubActivity with the timer running, the alarm will go off later, but I am left unable to reopen that activity in the meanwhile.
So how do I access the running timer activity?
Thank you!
Not clear what you want to achieve really, but it looks like wrong app design. If you want timer to run regardless of activity then you should decouple timer from activity and make activity just display the timer. Your timers should be elsewhere and definitely its lifecycle should not depend of actvity lifecycle.
I've got a bit of a dilemma and not quite sure how to solve it. Here's the scenario...
I have a multi activity application which plays music from the time it starts to the time the application exits.
However, if I use onPause / onResume to detect when the activity is sent to the background and pause the music in onPause and resume play in onResume, the music "skips" briefly when I start the next activity as the calling activity is finished once the startActivity() is called.
If I don't pause / resume the music in onPause / onResume the music plays smoothly but does NOT stop if the home key is pressed and the activity is sent to the back.
Is there a way to detect an activity is sent to the background (using, say a timer and application flag) without having to use onPause / onResume?
If this is not possible or too hard to implement (I'm still learning as we all are), is there a way to create an "invisible" launcher activity which runs in the background to handle such things but never seen?
As always, thanks in advance.
Turns out there's no simple way around this.
First thing you should do, is move your music streaming to a service, this way it doesn't depend on any activity.
Then you need to tell the service to stop when the entire application is in the background, not when one activity is paused. this fine answer suggests adding a timer to your application, and wait for a couple of seconds after an activity is paused. Of no other activity in the app is resumed - the app is assumed to be in the background.
I wouldn't add a timer to your application, but rather let your music playing service do this (notify the service in each onPause and onResume). Also, two seconds is too long for playing music, I'd start with 500ms and see if it's acceptable.
It's pretty simple IMHO
What you are trying to figure is if the new activity is from your application, continue playing the music, else stop.
You can do this with a boolean flag.
Here's the algorithm:
-boolean flag is set to true in onResume in all activities
-Keep the statements which pause the music in onPause
-Put the above statements (in onPause) in an if(boolean flag)
-whenever an event happens to start a new activity i.e. a button is clicked in your activities, etc, clear the flag (set it to false) in the event listener - eg: the button's onClickListener
This should work
The changeover between activities looks like this:
Activity A onPause
Activity B onCreate (or onRestart if it's already created)
Activity B onStart
Activity B onResume
Activity A onStop
You have a few options how to take advantage of this. You can subclass Application, and keep a boolean in the application class. Make a base Activity that does the following:
In onPause(), call the application to change the boolean to false.
In onResume(), call the application to change the boolean to true.
In onStop(), call the application to stop the music unless the boolean is set to true.
If all of your Activities extend this base Activity, then this will work. When A stops, as long as B was another one of your Activities, it will have resumed and set the boolean to true, so your music will keep playing.
There's a second approach that uses a Bound Service, where you bind in onStart() and unbind in onStop(). You can explore that on your own if you so desire.
You can (and in the fact should) use service to handle the music player. This is the component you are calling as "invisible activity".
If you start it by bindService() method in onResume and unbind in onPause() of each activity in your application it should run all the time. When no activity is bound to the running service the service is stopped by system, so all you need is just stop the music in the onDestroy() or in the onUnbind() method of the service.
Here you have a nice diagram of the Service lifecycle: http://www.tutorialspoint.com/android/android_services.htm
I'm not 100% if automatic management of servers lifecycle will be enough - in such case you can use startService() method to keep the service working all the time, when onUnbind of service is called put some delayed (i.e. using Handler.postDelayed(Runnable r) ) check if after i.e. after 1s service is still unbound and stopSelf() in such case.
OK, here's the solution and it's fairly straightforward once I thought about it in a more logical way.
What I have done is:-
Create a public static int called activityCount.
In the onCreate function of each activity I increment activityCount by 1.
I #Override public void finish() and decrement activityCount by one
and call super.finish().
In onPause if activityCount == 1, pause the music.
In onResume if activityCount == 1, play the music.
This is giving me the desired effect by continuously playing the music but when the home button is clicked the music stops and resumes when the activity is resumed.
Thanks for all the suggestions as it helped me think more logically.
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.
I have an Android app. I have a main activity, that has a button. When the button is clicked, another activity comes to the foreground. The thing is, I want to run a background thread that polls updates from the server. However, I want it to run only when the app is in foreground (either the main activity or the second one), and to stop polling when the user clicks the Home button or clicks the Back button till it's going back from the main activity.
But how do I know if the app is still in the foreground? I can catch the onPause of the main activity, but it's called also when I'm launching the second activity.
So how do I know when the app is in background?
Thanks
You should make a Service for the work you are doing in the background.
For stopping it when you click the Home or Back button, just make a listener for them and stop the Service when either one is pressed.
Seems easiest to me that each activity polls. Is it super important that it can poll when it is between the two activities? Otherwise you will have problems about knowing who is in front or not.
You can have a singleton with reference counting.
You main activity should add the first reference on it's onResume and from now, upon calling for every new activity (startActivity for example) you should add a reference.
Each activity should decrease the reference counting on its onPause.
Another option is to use services: Services