How can I keep background music playing whilst changing Activity? - android

My application has some background music playing on a loop, using a MediaPlayer. I stop the music in the onPause of the Activity so it doesn't keep on playing if the user leaves the application by pressing the Home key, or if they receive a phone call, etc.
However, I now need the music to continue playing seamlessly when the user moves to certain other activities. That is, if they press button A then I add activity A to the stack and the music should continue; however if they press button B then I add activity B to the stack and the music should stop. Similarly the music should continue if they press the phone's Back button to return from activity A to the original activity.
I've tried starting the MediaPlayer again in the onResume of Activity A, but there's quite a noticeable gap in the music during the transition.
At the moment I've got onPause triggering a half-second delay before fading the music out over another quarter of a second; this can be cancelled from within another activity's onResume. This means the music stops just about quickly enough when the user's leaving the app; however when the user switches activities I still get a slight pause in the music on some slower devices. Furthermore it feels like a really dirty hack.
Is there a better way?
[Edit: if it helps, the MediaPlayer is held in a static class that I can access from anywhere in the application.]

The simplest solution that I can think of offhand if I needed to get this done would be to set a static flag variable in my global Application object (let's call it sStartingNewActivity). Wherever I'm starting an intent new activity (or pressing "back" from an activity that isn't the entry point, overriding the onBackPressed method), I'd set that value to true, and have onPause not stop the music if that flag is set. I'd set the value back to false in every activity's onCreate. I don't think a 1-2-second-pause-before-fadeout is a bad way to go, though -- that would actually behave pretty similarly to how it works when the user presses the "home" button in an iOS app that has background music.
EDIT: You can also try a service-based solution that "sniffs" for whether your activities are running by having your activities listen for a specific broadcast; there's some sample code online that I haven't tried but it's an interesting approach).

Related

Programmatically put an Android activity in its "Stopped" state, without destroying it?

I'm creating a music app in Android with a background service playing the music, and a Home activity that has various fragments and is the UI of the app.
When I press the home button on my phone, this app gets put in the background of course, and the lifecycle methods get called down to onStop(), in which the UI gets disconnected from the Service in order to allow background playback, the user can keep using their device and do other things. When I get back to my UI Activity, onStart gets called and the UI and Service reconnect together, giving me back controls over the music. onStart gets me the same activity in the foreground, it doesn't create another instance of the same activity.
I'm trying to implement also a function for when I press the back button on my device, so the UI activity can have the same behavior as with the home button, i.e. simply put the UI in the background (onStop). Instead, the default behavior of the back button is to finish(), killing the current activity it's called from (thus calling onDestroy).
What could I do for that? Couldn't really find anything online. Seems such a simple function that every music app has (not killing the app when pressing back, but just send it into background)
You can override onBackPressed and move the Activity Task to back. Based on the documentation Activity'r order in the Task will also remain unchanged:
#Override
public void onBackPressed() {
this.moveTaskToBack(true);
}

Associate two activities with a service. Terminate the service if the application is put in the background

I have an activity A that starts a Music Service on a button click and optionally can start another activity B on another button click. I want the music to play in the background when the application is being used. When it is not being used (both Activity A and B are not visible) I would like the music to stop.
I've tried starting the service from Activity A on the button click using startService(mMusicIntent) and stopping in a similar way using stopService(mMusicIntent). The music does, indeed, stay playing as I jump between A and B, however if I am in Activity B and I put the application into the background (Home or switch app) the background Music service still plays. I can only stop the service using the onDestroy() method in Activity A.
Is there a better way of doing this? I don't want to pass data between either activities and the service (it simply plays music) so I didn't feel that binding was appropriate. But I could be wrong.
I ended up doing this with a bound service. I still don't know if this is best way to do something like this but it has the desired effect.
Activity A binds to the MusicService on the button click. In the MusicService we set the bind to start playing the music. Activity A unbinds when either the button is reclicked or Activity A is stopped. Activity B binds onCreate() and unbinds when onStop(). For sure I could probably tweak the code so that the correct lifecycle pairs are selected but this works for my use case.

pop up message from service provider(telecom network) causing activity to pause

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.

Check if onStop is called from user interaction, or screen dimming

I have a media player that stops playing whenever the user closes the app, either by pressing the home button, using the back button or simply opening another app.
To get this behavior, I added an onStop() to my main activity which tells my MediaPlayer(which is in a service) to stop playing music.
However, I would like the music to keep playing whenever the screen gets dimmed, either by using the power button to turn the screen off, or just by the screen auto dimming.
Right now the player also stops playing when the screen dims, meaning that the onStop() method also gets called then.
How can I check if the onStop() gets called by the screen diming?
I already applied a PARTIAL_WAKELOCK to my MediaPlayer object, which to the best of my knowledge, should make it possible for the player to keep running after the screen goes off.
Do I need to add a partial wakelock to my main activity as well?
Just applied a PARTIAL_WAKELOCK to both my main activity, as well as my media player.
Right now, the screen doesn't turn off by itself anymore, and when the user presses the power button the music still stops.
Obviously, this doesn't work as I thought it does.
Is there any way of achieving the behavior I'm looking for?
You can add
private boolean stoppedByUser = false;
field to your activity, set it to false in onStart(), to true in onBackPressed() and onUserLeaveHint() and check it's value in onStop() method.

Distinguishing between different Activity transitions

I have an Activity that plays some audio from within a ListActivity. The user can also click on the list item and go to a more detailed view of that data. I want the audio to keep playing during that transition from one activity to another and keep playing once the detail activity is active BUT I also need to pause the audio if my activity is being paused or stopped for any other reason.
My issue is that I currently pause the audio in onPause() in the ListActivity because I want the audio to be paused when the user navigates away from my activity. E.g. when they press Home or Back. However, I don't want the audio to pause when my detailed view activity gets started. onPause() is called in both instances, so how can I distinguish between the two cases?
Shouldn't you be doing that in a service instead? Wouldn't it be easier? Then you can stop the service when one or another activity is pausing or exiting (depending on which one you want). You could also check if it's started, and stop accordingly whenever you want.
Or sorry if I didn't understand your question. I see you have a lot of points here on SO, so perhaps I'm just confused.
--- edited since your third comment:
A Intent to B: send Intent with name of music.
B onCreate: get name of music from Intent. Set flag x to true.
B onResume: start playing music if from A or resumes from last known position if resuming from B.
B back button: override and set x to false. Actually, you'd cover all points where your activity finishes.
B onPause: stop the music if(x), store last known position of music in memory and stop service.
Here I assume that you want music to keep playing even when returning to A (that's what you said, that's the problem), not just up to B. Setting x is important early on, IMO, because if any other activity (phone call, anything) appears, activity will stop playing the music immediately (user expects that) on onPause. According to Android guidelines, you know that you're getting back to A only if user presses back button or if you finish() your activity. You can fine tuning checking the position of activities in your task (don't remember how to do that right now).
Personally, I also wouldn't want to resume playback on A (say, B->call->home->A, applying step 3 to A, too), because a disruption in the logical flow of things happens there.
CAVEAT: I would make sure that there is no other way. I would try to see if you can 1) know in advance which activity is about to be displayed. 2) get any music service to hook up to your task (is that even possible?).
Anyway, just use my solution if you can't find a clever way to do that. That would be my suggestion. Good luck.

Categories

Resources