I have tried to implement media button control per Google's talk
I set the receiver in manifest:
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<service android:name=".player.PlayFileService">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</service>
create the MediaSessionCompat
in onCreate()
of Service:
mediaSession = new MediaSessionCompat(getApplicationContext(), "SOUNDPROCESS");
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
PlaybackStateCompat ps = new PlaybackStateCompat.Builder()
.setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE)
.build();
mediaSession.setPlaybackState(ps);
mediaSession.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onPlay() { ...
}
});
and handle the intent in onStartCommand()
MediaButtonReceiver.handleIntent(mediaSession, intent);
I then call setActive(true);
when I gain audio focus, and setActive(false);
when I stop playback. This works the first time, my app becomes the preferred media button receiver and receives callbacks.
However, if I stop playback in my app, go into another app like Google Play Music and start playback there, then return to my app and call setActive(true)
Google Play Music continues to receive the callback and the media buttons don't work in my app.
From my understanding, the last call to setActive(true)
should take precedence. I have verified that isActive()
returns true. I can also work around the issue by creating a new MediaSessionCompat
each time, but this doesn't seem ideal.
How can I make my app become the preferred media button receiver every time I call setActive(true)
?
UPDATE: Minimum project to reproduce the problem here: https://github.com/svenoaks/MediaButtonDemo.git
Steps to reproduce:
setActive(true)
is called and
MediaButtonReceiver is now the preferred media button.setActive(true)
again. The other app always responds to media buttons.This was tested on Android 6.0.
My observations: (No enough reputations to comment, apologies, but I can reply to the comments for this answer)
'Run app, press the PLAY button. setActive(true) is called and MediaButtonReceiver is now the preferred media button': because Android first dispatches media button events to the foreground activity.
'Start playback on another app.......Press pause on this app........then return to my app and call setActive(true) ':
a) if you had called onStop listener before playing GooglePlay Music, then your media session is not active (until onPlay is called again) when you press any media button, and so the current session which is Google Play gets played.
b) If you hadn't called onStop then there are 2 active sessions (the first session of your app and the first session of Google Play. Second session won't be called unless OnPlay is called again). According to docs, if there are multiple active media sessions, Android tries to choose a media session that is preparing to play (buffering/connecting), playing, or paused, rather than one that is stopped.' So GooglePlay is the latest active session with paused state and gets played.
c) If you had called onStop (thus setActive(false)), and if GooglePlayMusic had also setActive(false), and you haven't clicked onPlay again then in that case too GooglePlayMusic will be played since "If there is no active session, Android tries to send the event to the most recently active session. On Android 5.0 (API level 21) or later the event is only sent to sessions that have called setMediaButtonReceiver()."
Have you setMediaButtonReceiver()?
https://developer.android.com/guide/topics/media-apps/mediabuttons.html Kindly have a look at it
The key to making this work correctly is to correctly set the PlaybackState
every time your app starts playing or pauses (which it should be doing when another app gains the audio session and activates its own MediaSession
. Without this, the problem as above will happen. Also, for Android 4.4 and lower, FLAG_HANDLES_TRANSPORT_CONTROLS
must be set or the same problem will happen.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With