I've got a simple Android app containing one Activity
and a Service
that derives from MediaBrowserServiceCompat
. I've successfully gotten it set up to play audio from my main activity by using MediaBrowserCompat
and MediaControllerCompat
. It can even play and pause the audio from my Bluetooth headphones. All good.
My challenge concerns the NotificationCompat.MediaStyle
notification that appears on the lock screen and in the notifications tray. The notification appears properly. However, when I add buttons using addAction()
and MediaButtonReceiver.buildMediaButtonPendingIntent
, they don't do anything. If I instead add a dummy PendingIntent that just launches my main activity, that works fine.
Here's my code to generate the notification (apologies, this is C# running in Xamarin, so the casing and names will be slightly different from what you might expect). This is inside my service class.
var builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetVisibility(NotificationCompat.VisibilityPublic)
.SetSmallIcon(Resource.Drawable.ic_launcher)
.SetContentTitle("Title")
.SetContentText("Content")
.SetSubText("Subtext")
.SetLargeIcon(icon)
.SetColor(Android.Graphics.Color.DarkOrange)
.SetContentIntent(intent)
.SetDeleteIntent(MediaButtonReceiver.BuildMediaButtonPendingIntent(this, PlaybackStateCompat.ActionStop))
.AddAction(new NotificationCompat.Action(
Resource.Drawable.ic_pause, "Pause",
MediaButtonReceiver.BuildMediaButtonPendingIntent(this, PlaybackStateCompat.ActionPause)))
.SetStyle(new Android.Support.V4.Media.App.NotificationCompat.MediaStyle()
.SetShowActionsInCompactView(0)
.SetMediaSession(this.mediaSession.SessionToken)
.SetShowCancelButton(true)
.SetCancelButtonIntent(MediaButtonReceiver.BuildMediaButtonPendingIntent(this, PlaybackStateCompat.ActionStop))
);
this.StartForeground(NOTIFICATION_ID, builder.Build());
Here's what I have looked at so far to try to solve this:
- When I start playback, I use
MediaSession.setActive(true)
- Each time I start and stop playback, I set the appropriate actions in
PlaybackStateCompat
- I have the session token set correctly.
- I do not have anything set up as a
MediaButtonReceiver
in my manifest, nor have I set anything up to handleandroid.intent.action.MEDIA_BUTTON
, because I am targeting Android 5.0 and higher and using the*Compat
classes, and my understanding is that that is no longer necessary.
I know that media button events are being routed properly to my app, since my Bluetooth headphone buttons work. I tried it in my car and it works there too. It's just the buttons in the notification that won't work. I'm expecting them to generate calls to the appropriate methods of MediaSessionCompat.Callback
. Is this incorrect? What am I doing wrong here?
I would be grateful for any pointers.
UPDATE:
I got it working. I needed to add the following inside the <application>
node of the manifest:
<receiver android:name="android.support.v4.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
...and the following inside the node of the Service that implements MediaBrowserServiceCompat
:
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
I'm still a little confused about why this was necessary, since button presses from my Bluetooth headphones and car infotainment system were routed to the app just fine. More importantly, Google says:
If you already have a
MediaBrowserServiceCompat
in your app,MediaButtonReceiver
will deliver the received key events to theMediaBrowserServiceCompat
by default. You can handle them in yourMediaSessionCompat.Callback
.
They gave this as an alternative to the option "Service Handling ACTION_MEDIA_BUTTON," so I took that to mean I didn't need to do anything more with my manifest. If anyone could enlighten me here, I would appreciate it.
But, for what it's worth, this worked for me.