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.
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.