Skip to content

currentMediaItem is empty when a CastPlayer is being used #25

Open

Description

@spun

I'm using a MediaLibraryService that switches the player from ExoPlayer to CastPlayer when a CastSession is available. When the ExoPlayer is active, calling getCurrentMediaItem() from a MediaController returns the correct MediaItem, but if the same call is done when the CastPlayer is the active one, I receive an empty MediaItem.

The method getWindow(...) inside CastTimeline is the one creating and using an empty MediaItem instead of the expected currentMediaItem.

Activity

  1. marcbaechinger commented on Jan 10, 2022

    @marcbaechinger
    Contributor

    This is a known issue which becomes more sever with AndroidX Media3 MediaSession. Implementing the Player interface properly is more important when we aim to be able to build a MediaSession with a MediaSession.Builder.

    For right now I'm afraid I can't really give a better advice than that you need to maintain your own list of MediaItems that represents the playlist and from where you can lookup the media item by index with the given window index.

    Somewhat aside: I think an approach to have a MediaSession with a Player that can change (local vs. remote playback with Cast) would be to have a custom Player implementation that delegates to an actual Player implementation and that allows to swap the actual implementation. It may for instance have a setPlayer(Player) method for swapping the current player with another. This way you can build a MediaSession with a MediaSession.Builder and delegate commands sent by a MediaController to either of the implementations under the hood. If you do that, that custom Player implementation would be the best place to maintain the list of MediaItems that is the playlist. It can also help you to work around #26 that is related to the CastPlayer not properly implementing the Player interface in the current state.

    --
    Some comments for context when someone is going to fix this (I stick with the bug label because I agree this is now a bug in context of AndroidX Media3):

    There is an unwritten contract that a Player should provide an equal MediaItem with Player.getMediaItemAt(int index) that have been passed to the set/addMediaItem(MediaItem) methods. The same should be the case for Timeline.getWindow(...) as well.

    CastPlayer currently fails to do that which we need to improve. At the very least CastPlayer should propagate the mediaId correctly which would be a first step although if we fix this that way we probably should comply with the whole MediaItem because the mediaId is not necessarily unique. There is a commit in the ExoPlayer repo for the dev2 branch which includes the mediaId when un/marshalling which is a first step towards this. CastTimeline is another step as mentioned above in the user's post.

  2. spun commented on Jan 10, 2022

    @spun
    Author

    Thank you very much @marcbaechinger for the idea of the custom Player. I was able to fix the empty MediaItem problem with a modified CastTimeline, CastTimelineTracker and a custom MediaItemConverter (like you already said, the default is a bit limited), but your idea is way better than calling MediaSession#setPlayer(...) each time the player changes. By the way, something like that inside the media3-cast would be awesome.

    Thanks again!

  3. NielsMasdorp commented on Feb 13, 2022

    @NielsMasdorp

    @spun Could you elaborate how you managed to solve the empty MediaItem? I am currently relying on onMediaItemTransition and onMediaMetadataChanged callbacks inside my MediaController and I need the mediaId and mediaMetadata in said callbacks. Obviously this doesn't work when I switch to the CastPlayer in the MediaSessionService.

  4. spun commented on Feb 14, 2022

    @spun
    Author

    Hi @NielsMasdorp. Unfortunately, I decided to wait until the issue is fixed. I'm currently running a modified version of the library with some changes made to CastTimeline (I could link you a Gist with the changes if you want) to fix the empty MediaItem problem until something is implemented in media3.

    You could try the custom Player that switches between local and cast and also maintains the list of MediaItems. It's still a promising solution but, when I tried to do it, I was a bit overwhelmed with the RemoteMediaClient also being able to change the list of MediaItems and I don't have a working implementation yet.

    If you can wait, when this issue is fixed, we should be able to at least retrieve the mediaId from the "empty" MediaItem. I think there was already a first step, but CastTimeline still returns the empty one, so we'll have to wait a bit longer.

  5. NielsMasdorp commented on Feb 14, 2022

    @NielsMasdorp

    @spun Thanks for the update. In the meantime i've decided to tackle the problem as well. I am currently working on my own implementation of a custom Player which indeed switches from local to cast internally. It works, but it is tailored to my use case. I don't have a list of items but only playback a single MediaItem at a time, so the solution is just to keep a reference to the current MediaItem and that's that. But I am sure i've missed some edge cases. After that I will wait for updates in the media3 implementation (or at least a CastPlayer which implements the Player correctly).

  6. tonihei commented on Jul 15, 2022

    @tonihei
    Collaborator

    Fixed by the commits above.

  7. 1 remaining item

  8. Djsolutions1 commented on Oct 19, 2022

    @Djsolutions1

    Nice work

  9. NielsMasdorp commented on Mar 1, 2023

    @NielsMasdorp

    @marcbaechinger Sorry to open this again, but during active play of CastPlayer getCurrentMediaItem() returns the correct MediaItem however when listening to onCastSessionUnavailable() callback and subsequently checking getCurrentMediaItem() it is empty again. Is this intentional? Looking at the source it seems that the Timeline is cleared by the CastPlayer before the onCastSessionUnavailable() callback is invoked.

    This means we still have to resort to locally caching the MediaItems, no? Or am I missing something?

  10. marcbaechinger commented on Mar 1, 2023

    @marcbaechinger
    Contributor

    When the remote media client is set to null the timeline is updated and set to an empty timeline. I agree that's surprising and unfortunate for a Player implementation, specifically that this happens before the callback is called.

    we still have to resort to locally caching the MediaItem

    I think this is a known behaviour though. CastPlayer is missing abilities to nicely connect/reconnect. To resume playback, the playlist media items need to be set again. Apps probably mostly maintain the playlist, position, window index and the like to be able to either setup a local ExoPlayer or CastPlayer like PlayerManager in the demo app. UAMP uses a ForwardingPlayer.

    However, now that we support the media items in the timeline with CastPlayer, we could and probably should do better. Re-opened to track decoupling cast session and CastPlayer state and keeping timeline, currentMediaIndex and currentPosition when the cast session ends (probably similar to when ExoPlayer.stop() is called). Then we probably also need to think about the behaviour when the session/remote media client returns again.

    I don't know when we come around to look into this I'm afraid .

  11. NielsMasdorp commented on Mar 2, 2023

    @NielsMasdorp

    Thank you, seems logical. I was just verifying to be sure I didn't miss anything. I'll keep an eye on improvements in the future.

  12. TomasValenta commented on Nov 6, 2023

    @TomasValenta

    Thank you for this comment @marcbaechinger. I stumbled upon it accidentally, I wish I could have read it before e.g. in README, it would have saved me a lot of time and debugging.

  13. fdfmobileapps commented on Nov 17, 2023

    @fdfmobileapps

    Hi @marcbaechinger

    Just wondering if there were and updates on The empty media item issue?

    It presents quite a significant problem, when resuming of a session is required. Caching a copy of the playlist, for the purpose of recovering from a Cast connection loss, if fairly ugly and highly prone to issues.

    I am working around it by retaining a playlist of current items, which I reference rather than metadata on castplayer. I do this to avoid re-pushing a play queue if a resume is required. It's not ideal, due to potential to become out of sync, if queue items change for example. Have to be very careful to keep that list in sync on queue edits and so forth

    I have noticed that the notification published by media 3 seems to have awareness of metadata post resume. I Was wondering how the notification is obtaining this information?

    Cheers

  14. fdfmobileapps commented on Mar 17, 2024

    @fdfmobileapps

    Hi @marcbaechinger

    Was wondering if you had any updates or further advice on this issue, as yet?

    Cheers

  15. added a commit that references this issue on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions