Customising Jetpack Media3 player notification — Chapter III — Rearranging buttons order

A Poplawski
3 min readNov 16, 2023

--

Background

I recently got a chance to work on Media3 player notification for my current company. Even though the task seemed easy at first, I found it to be relatively difficult, because:
- There was no official guide on the “go to way” to customize player notification.
- Multiple sources still referencing PlayerNotificationManager. As Media3 documentation says:

The PlayerNotificationManager from ExoPlayer is no longer needed, as Media3’s MediaSessionService and MediaLibraryService automatically handle publishing a media notification as needed.

I will share with you the journey in a form of simple, step-by-step guide on how to customise player notification with Media3.

We will go from this…

Default state for notification player

To this…

Desired state with rewind/forward commands

Steps required:
1. Add rewind/forward custom commands
2. Override play/pause icons
3. Rearrange commands on the notification to achieve [REWIND, PLAY/PAUSE, FORWARD] order

NOTE: Even though notification UI may differ on your device, depending on the brand, model and Android system version, steps mentioned in this guide should still bring us to the desired end result.

Implementation — Chapter III — Override notification icon resource

As you know from chapter I of the article, play/pause is a default action. We also added custom rewind and forward actions.

Here’s what we ended up with:

But the requirement is — play/pause action has to be in the center, with rewind on the left and forward on the right.

Here’s how we can achieve this.

DefaultMediaNotificationProvider.addNotificationActions()

We extend DefaultMediaNotificationProvider and overriding its addNotificationActions() function to intercept and modify mediaButtons list before notification is rendered.

@UnstableApi
class CustomMediaNotificationProvider(context: Context) : DefaultMediaNotificationProvider(context) {

override fun addNotificationActions(
mediaSession: MediaSession,
mediaButtons: ImmutableList<CommandButton>,
builder: NotificationCompat.Builder,
actionFactory: MediaNotification.ActionFactory
): IntArray {
/* Retrieving notification default play/pause button from mediaButtons list. */
val defaultPlayPauseCommandButton = mediaButtons.getOrNull(0)
val notificationMediaButtons = if (defaultPlayPauseCommandButton != null) {
/* Overriding received mediaButtons list to ensure required buttons order: [rewind15, play/pause, forward15]. */
ImmutableList.builder<CommandButton>().apply {
add(NotificationPlayerCustomCommandButton.REWIND.commandButton)
add(defaultPlayPauseCommandButton)
add(NotificationPlayerCustomCommandButton.FORWARD.commandButton)
}.build()
} else {
/* Fallback option to handle nullability, in case retrieving default play/pause button fails for some reason (should never happen). */
mediaButtons
}
return super.addNotificationActions(
mediaSession,
notificationMediaButtons,
builder,
actionFactory
)
}
}

Now, in your class that implements either MediaLibraryService or MediaSessionService, we’ll need to set our custom media notifications provider.

class PlayerService : MediaLibraryService() {

private val customMediaNotificationProvider: CustomMediaNotificationProvider by inject()

override fun onCreate(): MediaSession.ConnectionResult {
super.onCreate()

// ... implementation.

setMediaNotificationProvider(customMediaNotificationProvider)
}
}

That’s it. Let’s build the app and see the end result.

We have it! Thanks for reading my friend! I write more about Android, Kotlin and programming itself, so if you’re interested in this topic, consider following and seeing my other articles.

Chapter I: https://medium.com/@a.poplawski96/customising-jetpack-media3-player-notification-chapter-i-adding-custom-commands-3cd16256e0e0
Chapter II:
https://medium.com/@a.poplawski96/customising-jetpack-media3-player-notification-chapter-ii-overriding-notification-icons-bc2225ee6441

And also, let’s connect!
https://www.linkedin.com/in/apoplawski96/

--

--

A Poplawski

Creating Android apps since 2019 - Android, Android TV & Kotlin Multiplatform. Trying to share useful information in a digestible manner.