I decided to write simple alarm clock (using AlarmManager). When alarm works out I want to show simple dialog with 2 buttons: OK and Snooze. So I have a question: what should I connect with my Pending Intent? I mean Service, Activity or BroadcastReceiver?
At present version I use BroadcastReceiver where I start Activity that shows the dialog. I start it with flag FLAG_ACTIVITY_NEW_TASK. In onStrat() method I start music service. When OK button's pressed I call finish() for activity and stop music. In OnPause() I call finish() also. I do it because if two alarms run simultaneously then according to activity life cycle method onPause() will be called. It works... but sometime the music starts for a few seconds then finishes....then start again and finishes and so on. Why? Thanks.
So I have a question: what should I connect with my Pending Intent? I mean Service, Activity or BroadcastReceiver?
Probably an activity in this case. Theme your activity to look the way you want (e.g., Theme.Dialog) rather than fussing around with a regular dialog box.
It works... but sometime the music starts for a few seconds then finishes....then start again and finishes and so on. Why?
It is impossible to answer this question with the information you have supplied, sorry.
Related
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 a foreground service that calls StartActivity on ActivityA. If ActivityA is not in the foreground, it is displayed to the user. If the Activity is in the foreground, the service still calls StartActivity, and the activity receives a new Intent and updates itself accordingly.
The user may interact with ActivityA which will display ActivityB as a popup (Theme.Dialog), during which ActivityA is paused. Now if the service detects another event, it calls StartActivity again. This time though, I do not want to navigate to ActivityA. I want the user to still see the ActivityB popup and have ActivityA update itself in the background.
Is there any flags I could add to the intent which the service starts which will prevent navigation to ActivityA if it is Started but Paused?
Other Info :
1. If I have ActivityA bring ActivityB back to the foreground, ActiviyB end up flickering and just doesn't look good.
2. Have the service use ActivityManager to determine if ActivityB is displayed. If it is, broadcast an intent which will be listened to by ActivityA and force it to update, instead of calling StartService. But this couples the Service with two activites, needs more coding, and will force me to synchronize the service call onto the main thread to avoid timing issues.
I am really hoping there is something simple that I can do like set some flag on the intent. Or catch the intent within ActivityA, update the activity, but cancel the intent to prevent the screen navigation.
Any suggestions?
Note: Not using Android notification bar. Understand that starting activities from service is not recommended. We have a specific need for this.
Yes you can, if you are binding your service.. call bindService(mConn); in onResume() of your activity and unBindService(mConn); in onPause()..And in your service class, #Override the onUnbind() method and you can set the flag there.
I hope it was useful.
It sounds like you might want to use AtomicReference from java.util.concurrent.atomic to pass the right intent to start activity. I haven't actually tried this, but its probably a good place to start.
I don't want the notification service to be working while the user is in the application. As of right now I have it starting in the onCreate and onResume methods and stopping in the onPause method. Is that correct?
Also, is it sufficient to specify the intent and execute stopService(intent) to stop it? There isn't a direct relationship between the start and stop methods except they reference the same class.
Thank you for any help.
Here is the activity lifecycle.
As you will see, onCreate() and onResume() are called before the activity is created so you do not want to start your notification service there. You should stop it instead. It is a good idea to do it once in onResume() because it is the entry point of your activity.
onPause() is where user navigates away from the activity so it is where you will want to start the service again.
I've found out that pop up messages from my service provider(telecom network) is causing my app activity to get paused.Is there any way i can prevent these from pausing my activity?
I am not sure if there is much that you can do about blocking the pop ups from the service provider.
The easiest way to handle this situation though would be to shift your countdown timer or ringtone player to a background service.
What happens now is that when these pop ups occur your service is temporarily loses its focus and gets the focus back when the pop up is closed. Implementing your timer and stuff in the service will prevent this from happening.
EDIT:
best way is, write the entire layout as you want with all the buttons. in the onclick of activities you can call whatever the intents that you want. At the same time you can make the countdowntimer and ringtoneplayer as static objects in service.
So in the activity when you press the start button, you can just write service.countdowntimer.start() and it will start the cdt from the activity and the same for stopping the time and for the ringtone player too. You are just shifting your ringtone player and cdt to the background and implementing it in another class which extends service. rest almost everything remains same. you wont even need any sort of listener here.