media
media copied to clipboard
Correct behaviour when switching `Player` in `MediaSession`
As per #25 i've implemented a custom Player
which caches the MediaItem
(s) internally and switches from local playback using an ExoPlayer
instance to a CastPlayer
instance when a cast session is available and vice versa. This composite Player
is passed to the MediaSession
and no subsequent calls to MediaSession#setPlayer
are made.
player = CompositePlayer(localPlayer = localPlayer,castPlayer = castPlayer)
mediaSession = MediaSession.Builder(this, player)
The way I am currently switching players internally is: stop the playback of the current player using player#stop()
and clear the playlist in the current player using player#clearMediaItems()
. Afterwards set the items to the new player using player#setMediaItem()
, player#prepare()
and player#play()
.
This all works fine, except when switching from local playback to cast playback a new cast notification is created, yet the "old" media notification is also still present (however it shows the device name of the device I am casting to, instead of "phone"), so theres 2 notifications at the same time, also the "old" notification is not updated anymore (presumably because it is connected to the old local playback which is not used anymore?).
My question: what is supposed to be the correct UX? Is there something wrong with my implementation? I feel like there should only be 1 notification: a cast notification when casting and 1 notification when using local playback. Also since I am using a PlayerControlView
in the UI this is only connected to one player, either local playback or cast playback depending on what's active at the moment.
I am running a Pixel 4a with Android 12.
What would be the preferred option for you as a developer?
I would want to have a single place where I can configure how the notification looks like and whats written into the media session. Being an Android app I would think I do that with the media session that I need to maintain with my Android app. If there is a cast device involved temporarily I would want that I don't have to do the same customisation and session maintaining again.
I wouldn't care from where this session and notification is coming, but because I develop an Android app I need to maintain a session and a notification as long as my Android app is alive. The Cast session and notification is not helpful here because it can't manage my session/notification when I'm not casting.
I would also expect that someone who listens to my media session while my local playback is running doesn't have to know that my app may create a second session while I'm casting. So I want to have consistently the same session for my app.
So for the reasons above I as a developer would want that Media3 is maintaining a single session and a single notification for the lifetime of my app. That is simplest for myself as a developer and it is less confusing for an external app that wants to interact with the session of my app.
I would be interest to hear you opinion regarding this.
I would also be interested whether it helps if you change you CastOptionsProvider
and add there:
.setCastMediaOptions(
CastMediaOptions.Builder()
.setMediaSessionEnabled(false)
.setNotificationOptions(null)
.build()
)
Yes, I would agree that from a developer perspective it is logical to maintain a single MediaSession
which in turn manages a single notification which can switch between a "cast notification" and a "local notification". However I am not sure what a "cast notification" should look like and how to achieve this behaviour with the current media3 state.
Current behaviour:
Local playback (default state without initialising a cast session)
After initialising cast session and thus resetting the ExoPlayer
instance in the Composite Player
and starting the CastPlayer
another notification is shown and the other notification changes state (note the badge which specifies the casting device). This is kind of expected since there are 2 MediaSession
s now, one created in my Service
and one in the Cast SDK.
Imo it is kind of confusing to have 2 notifications with playback controls and one notification with a close action (which stops the casting session).
When I disable the media session and notification options in the OptionsProvider
the result is as expected:
There is always 1 notification showing and the only thing that changes when changing from local playback to remote playback is the badge on the right showing the device name:
However that notification does not show the google cast logo next to the artwork and there is no close button to stop the casting session. Which, from a user perspective, is unexpected.
What I would expect:
Always 1 notification and with local playback:
And when I switch to cast its only this notification:
However I am not sure this is currently possible with one single MediaSession
.
As extra clarification: I am not creating/managing any notifications myself, these notifications are all created by media3 internally.
Gist of my implementation:
https://gist.github.com/NielsMasdorp/d22c9286aa1bd3e1629258d156e7c6e2
@marcbaechinger Thinking about it I could probably add a custom close action to the notification when a cast session is active and sort of have the same effect was going for in the first place. And reach our preferable outcome: one single notification and one MediaSession
per app.