androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.63k stars 386 forks source link

Media3 backwards compatibility with PlayerNotifcationManager #1019

Closed cemore2048 closed 7 months ago

cemore2048 commented 8 months ago

When migrating to media3 I realize we should not have to need PlayerNotificationManager but for now we're keeping it in our codebase. I'm running into issues where our notification no longer really sets the media style like it did before the update unless I turn my notifications off.

Before, it looked like this Screenshot 2024-01-24 at 12 18 47

Now it gets clumped into the rest of the notifications and the style has changed. Screenshot 2024-01-24 at 12 29 14

I'm starting the foreground service building a regular notification, setting the MediaStyle with the mediaSession

class ConversationService : Service() {

private fun configureNotification(conversation: Conversation, bitmap: Bitmap?) {
        val notification =
            NotificationCompat.Builder(this, channelId)
                .setLargeIcon(bitmap)
                .setOngoing(true)
                .setSmallIcon(com.clubhouse.core.ui.R.drawable.ic_hand_wave)
                .setStyle(MediaStyleNotificationHelper.MediaStyle(mediaSession))
                .setContentTitle(conversation.title)
                .build()

            startForeground(ClubhouseNotifications.VOICE_MESSAGE_NOTIFICATION_ID, notification)
}

We're building the media session in the same way,

@UnstableApi
    fun setActiveConversation(conversationId: String?, player: Player? = null) {
        val lastActiveMediaSession = _activeMediaSession.value
        if (conversationId != null) {
            if (lastActiveMediaSession?.id != conversationId) {
                lastActiveMediaSession?.release()
                _activeMediaSession.value = MediaSession.Builder(
                    applicationContext,
                    player ?: object : SimpleBasePlayer(
                        Looper.getMainLooper(),
                    ) {
                        override fun getState(): State {
                            return State.Builder().build()
                        }
                    },
                ).setId(conversationId).build()
            }
        }

and in a wrapper we built for the player, I'm setting the player on the notificationManager.

class SegmentAudioPlayer @Inject constructor(notifiicationManager: PlayerNotificationManager) {

    fun prepare() {
         exoPlayer.prepare()
            notificationManager?.setPlayer(player)
            startPlaybackUpdates()
    }
}

Besides getting rid of some of the Compat classes that no longer exist these things that I highlighted were happening pre adding media3. Is there a reason due to the updating to media3 that the media style isn't getting set? Is it due to the fact that we're still using the playerNotificationManager?

Edit

We weren't setting a mediaSession on the notificationManager: PlayerNotificationManager before. I'm attempting to do that, but it requires the support library that I can't pull into my project. Simply calling

notificationManager.setmediaSessionToken(mediaSession.sessionCompatToken) results in a Cannot access class 'android.support.v4.media.session.MediaSessionCompat.Token' error at compile time.

These are the media libraries that I'm using, but I'm guessing that media3-session isn't using the api dependency handler for the android.support.v4... in it's imports?

api("androidx.media3:media3-exoplayer:${Versions.exoplayer}")
api("androidx.media3:media3-ui:${Versions.exoplayer}")
api("androidx.media3:media3-session:${Versions.exoplayer}")
api("androidx.media3:media3-exoplayer-hls:${Versions.exoplayer}")
tonihei commented 8 months ago

Generally, Media3 recommends to use the MediaSessionService or MediaLibraryService instead of a hand-written service. This is because these services handle all the API version differences internally and also automatically generate the right notification for you. As this is handled internally, classes like PlayerNotificationManager are no longer needed. I hope this explains why it only takes a legacy session token.

See https://developer.android.com/media/media3/session/background-playback and https://developer.android.com/media/media3/session/serve-content for more details.

To your actual question: the behavior depends a bit on which API level you are running this on (e.g. on API33+, the media style is not really relevant anymore because all information is taken directly from the MediaSession). And given the symptoms, I get the impression that multiple notifications may compete for the main playback slot and one of them gets downgraded to a "normal" notification? This is just guessing though without having a proper explanation where this happens. Your edit also suggests that the media session token wasn't set at all initially?

media3-session isn't using the api dependency handler for the android.support.v4... in it's imports

This is WAI. If you want to use the android.support.v4. classes you have to add the dependency yourself.

cemore2048 commented 8 months ago

And given the symptoms, I get the impression that multiple notifications may compete for the main playback slot and one of them gets downgraded to a "normal" notification?

Yea this is essentially exactly what happens. I start a foreground service but the startForeground call that's required needs a notification. I think maybe we were getting lucky earlier with how it was displaying.

Separately the notificationManager.setPlayer(player) doe it's thing to se the notification.

Your edit also suggests that the media session token wasn't set at all initially?

This is correct, I think somewhere we were just getting lucky.

I'm not able to import the support libraries due to conflicts with the androidx pieces, so it seems the only option is to fully commit to the MediaService

tonihei commented 8 months ago

I'm not able to import the support libraries due to conflicts with the androidx piece

That should not be problem actually. What is the issue that prevents you from accessing from both libraries?

cemore2048 commented 8 months ago

Whenever I try to import them it gives me this error on the ide. Then building gives me a manifest merge error that I'm assuming is juts a symptom of what the ide error is calling out

Screenshot 2024-01-26 at 11 55 15

tonihei commented 8 months ago

I think you need include androidx.media:media:1.7.0 instead.