I want to start my app/service when another app get's active or music is played from that app. Is this possible with Android?
If You are specifically looking for starting your service when music player starts, take a look at AndroidManager API. You can register for callbacks using
registerAudioPlaybackCallback
Also there is method from same AudioManager which tells you if Music isActive
isActive - Stackoverflow
isMusicActive
Related
I'm trying to be able to start music playback from my app when the headset buttons are clicked while my app is stopped.
I can use MediaSession.Callback onMediaButtonEvent() or the now deprecated registerMediaButtonEventReceiver() to listen for media button click WHILE my app is playing music, but if I pause the music for a minute, with my Activity and playback Service still running, and then I press the headset button, I see that I have lost the ability to receive the media button broadcast. Instead, Google Now opens.
What I'm trying to do is something like Google Play Music. It is able to start music playback even if the app is completely stopped...no services in the background.
I feel that setMediaButtonReceiver() is the one to use for this, but I've not been able to get it to work.
setMediaButtonReceiver(PendingIntent mbr)
Set a pending intent for your media button receiver to allow restarting playback after the session has been stopped. If your app is started in this way an ACTION_MEDIA_BUTTON intent will be sent via the pending intent.
I have the following snippet in my Service.
PendingIntent pi = PendingIntent.getBroadcast(HeadsetService.this, 0, new Intent(HeadsetService.this, RemoteControlReceiver.class), 0);
mMediaSession.setMediaButtonReceiver(pi);
My RemoteControlReceiver BroadcastReceiver is registered in the Manifest but I receive no broadcast when I press the button.
I've also seen that other music player apps lose the ability to receive media button broadcasts once they've stopped playback for about minute.
Any ideas how I can have a more robust media button controls?
Thanks in advance!
First, it is important to distinct MediaSessionCompat from any service such as MediaBrowserServiceCompat.
MediaSessionCompat is communicating with the external MediaSessionStack that dictates which app will get media key commands from external MediaSessionService. On API 26+ the key will be sent to the last playing app. Devices with API < 26 will first look for active playing/buffering session, then for active session and then for last playing session. The latter allows apps to 'steal' the focus by keeping the mMediaSesssion.isActive tag on when they shouldn't. More details about priority can be found in the official guide.
So as long as your app set mMediaSesssion.isActive = true at some point and was last playing, it will get media keys unless mMediaSession.release() was called. The latter removes your session from MediaSessionStack and thus will your session no longer receives media keys. That's why it is important to call release() once you no longer expect user to continue playing video or music. There is one more caveat: If system thinks your app was killed as opposed to ended gracefully, then the app is removed from MediaSessionStack as well, which makes sense, because in service onDestroy() is not necessarily called in such scenario and thus the system releases your session for you. This might happen when you swipe away the app. A workaround I use is to keep the service in foreground while the main app is in use and then end the service after a short delay upon receiving a call to onTaskRemoved() in service.
The call to mMediaSession.release() will happen at some point if you put it in onDestroy() of your service. The service is expected to end when it is not being used, as otherwise it is taking system resources. Thus, it is recommended to end it in onStop() command or when swiping away app or notification. In your case it may happen that power manager killed your service after being inactive for some time. Depending on implementation the some parts of the player might still be working even if the service is destroyed. Also the notification might still be there, as the service is no longer in foreground. That might've fool you into thinking that the service was running. Though without more details, I cannot really say what exactly went wrong in your case.
One additional cause that might prevent your app from getting media keys is if your manifest is not properly configured. Make sure that your BroadcaseReceiver entry includes android.intent.action.MEDIA_BUTTON intent filter.
Another possible mistake is initializing your media key callback MediaSessionCompat.Callback() in the service or any other lifecycle component. Thus, if that component gets destroyed, it can quickly lead to unexpected behavior.
TLDR:
Filter your Logcat for MediaSessionStack|MediaSessionService to ensure that your app gets the media keys. If it doesn't, then:
ensure that mMusicService.isActive = true is set (in e.g. in onPlay())
ensure that mMusicService.release() is not called
ensure that your manifest is properly set
ensure that the system doesn't think your service was killed (e.g. by swiping away the app) as opposed to being ended gracefully
Then make sure your app is handling media keys properly.
In case of custom receiver, they should be there.
In case of androidx.media.session.MediaButtonReceiver they should be in MediaControllerCompat.Callback() whose state should not depend on any service or lifecycle component
I wrote the answer a little bit more general, since it is an old question and others might benefit from it more than the OP.
Basing on this example: https://www.binpress.com/tutorial/using-android-media-style-notifications-with-media-session-controls/165
I've created a service which playing audio stream from URL with control buttons in notification - I can pause, resume and turn off streaming (by stopping service).
But how can I control this from activity, just like from notification? Of course I can send intents with proper action, but what I want is (for example):
I have opened activity from where I start service, music is playing and then I pull down a notification drawer, kicked pause for example, music is paused but activity is not aware about this
So there is my question - is there any possibility to access running Media Session or something like that from activity and control it just like from notification?
You need to bind your activity to your service, then add activity as listener to the player, and every time you start, pause ...etc report to your listener (activity). You will need to create your Interface to report such details to whoever wants to track the player's events.
Alternatively, you can use the new MediaSession compat libraries in the android support libraries found here:
https://developer.android.com/guide/topics/media-apps/index.html
They simplify the process of creating media controllers and establishing the transport control channels for wiring user interface components to media control service classes.
I have Implemented A media player But the Problem is that when i press back button .music stop.but it runs when the app is in background.
Proper approach is to implement media-player inside service. That way music playback will persist when users uses other applications or gets outside of your app.
Remember to call startForeground() with ongoing notification.
I'm making a internet radio android application that streams using MediaPlayer. However, I want it to continue streaming music in the background when the phone is locked, or I'm using another application.
I can't find anything online for this and it's very frustrating, does anyone have any solutions or tutorials I can use?
You need to use a service and you can play media player from there, you probably will need your activity later to communicate with your service to get some information from the player ( by binding your activity to the service or using broadcast receiver)
I am making an app in which I've made a Service which plays Music from URLs. The thing is that my music Service is playing music correctly BUT when user plays any song with Native music player then BOTH(Native Player and My Music Service) are playing music simultaneously. I want to stop My Music Service when user started playing music with native player.
Is there any Broadcast Intent which i can register to Detect the
music player is started?
Is it possible to detect Music player Started?
Any Other Solution?
Any suggestions would appreciated.
I'll suggest a different approach, that I believe it's the correct approach.
the issue on your approach is that you're suggesting to check for one specific app. And there're tons of different music players, plus radio players, plus video players, plus games... and all of those should stop your music in case they want to play something.
So how you do it?
It's all explained in the Android Developers website.
You have to register an OnAudioFocusChangeListener, so, whenever a different app request to have the audio focus, your app can stop the music.
Step 1: Detect if the user has opened native music app. For this , you need to know the package name of your native music app.
Then refer to my answer here: Android how to know an app has been started and range apps priority according the starting times
Using that , the list taskinfo will have the list of all running activities, and as explained there, the first element of the list will be the activity in the foreground.
STEP 2: Once you detect native music app being activated using STEP 1 (by polling for it in the background) , then stop your app's service.
NOTE: You should do this in a background (using asynctask) or another service.
NOTE 2: The limitation of this method is that you can't actually stop the music player when the user clicks play in the native music app, since this method will help you detect only if the native music app is opened or not.