androidx.media3.common.util.Assertions.checkState(Assertions.java:85)
Version
Media3 1.4.0
More version details
api("androidx.media3:media3-exoplayer:1.4.0") api("androidx.media3:media3-session:1.4.0") api("androidx.media3:media3-common:1.4.0")
Devices that reproduce the issue
Customized in-vehicle infotainment system, using Android 13.
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
No
Reproduction steps
1.My multimedia application uses exoPlayer internally, and there's a requirement to switch the player when changing audio sources. Therefore, I'm binding a player to the MediaLibrarySession using: MediaLibrarySession.Builder(this, switchablePlayer, this). The problem tends to occur when the internal audio source switches from Bluetooth to USB update list to exoPlayer:
override fun onUsbPlaylistChanged(playlist: List<MediaItem>) {
MediaLog.i(TAG, " onUsbPlaylistChanged playlist ${playlist.size}")
currentMediaList.clear()
currentMediaList.addAll(playlist)
exoPlayer?.clearMediaItems()
exoPlayer?.addMediaItems(currentMediaList)
}
2.when I need Play ,changing the internal player accordingly
fun switchPlayer(newSmartPlayer: SmartPlayer?) {
MediaLog.d(TAG, "Switching player: ${currentSmartPlayer?.javaClass?.simpleName} → ${newSmartPlayer?.javaClass?.simpleName}")
currentPlayer?.removeListener(forwardingListener)
currentSmartPlayer = newSmartPlayer
currentPlayer = newSmartPlayer?.getPlayer()
currentPlayer?.addListener(forwardingListener)
MediaLog.d(TAG, "Player switched, listeners: ${listeners.size}")
currentPlayer?.currentMediaItem?.let { item ->
mediaItemChangeCallback?.onMediaItemDataChange(item)
}
}
3.This player switching is done within SwitchablePlayer.
I will call the play logic.
override fun playMediaByItem(mediaItem: MediaItem) {
MediaLog.d(TAG, "playMediaByItem: ${mediaItem.mediaMetadata.title}")
MediaLog.d(TAG, "playMediaByItem: ${mediaItem.mediaId}")
val index = findMediaIndex(mediaItem)
if (index >= 0) {
playMediaAtIndex(index)
} else {
MediaLog.w(TAG, "Media not found in playlist: ${mediaItem.mediaId}")
}
}
private fun playMediaAtIndex(index: Int) {
if (index >= 0 && index < currentMediaList.size) {
exoPlayer?.seekToDefaultPosition(index)
exoPlayer?.prepare()
exoPlayer?.play()
MediaLog.d(TAG, "Playing media at index: $index")
} else {
MediaLog.w(TAG, "Invalid index: $index, playlist size: ${currentMediaList.size}")
}
}
Expected result
The usb music media play successfully
Actual result
Playback crashes with the following stack trace
11-03 19:11:19.734 3824 3824 E AndroidRuntime: Process: com.smartlink.multimedia, PID: 3824
11-03 19:11:19.734 3824 3824 E AndroidRuntime: java.lang.IllegalStateException
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.common.util.Assertions.checkState(Assertions.java:85)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.session.PlayerInfo$Builder.build(PlayerInfo.java:381)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.session.PlayerInfo.copyWithTimeline(PlayerInfo.java:597)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.session.MediaUtils.mergePlayerInfo(MediaUtils.java:149)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.session.MediaControllerImplBase.onPlayerInfoChanged(MediaControllerImplBase.java:2715)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.session.MediaControllerStub.lambda$onPlayerInfoChangedWithExclusions$9(MediaControllerStub.java:258)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.session.MediaControllerStub$$ExternalSyntheticLambda13.run(Unknown Source:4)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.session.MediaControllerStub.lambda$dispatchControllerTaskOnHandler$14(MediaControllerStub.java:374)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at androidx.media3.session.MediaControllerStub$$ExternalSyntheticLambda6.run(Unknown Source:4)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:942)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:99)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:201)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at android.os.Looper.loop(Looper.java:288)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:8061)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:703)
11-03 19:11:19.734 3824 3824 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)ra
Media
I will send you the relevant demo via email
Bug Report
- [x] You will email the zip file produced by
adb bugreportto [email protected] after filing this issue.
I think your failure occured here:
https://github.com/androidx/media/blob/bfe5930f7f29c6492d60e3d01a90abd3c138b615/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java#L380-L384
I'm assuming that when you replace the media items, you trigger MediaSessionImpl.PlayerListener.onTimelineChanged -> session.playerInfo.copyWithTimelineAndSessionPositionInfo which then sets the timeline AND builds the PlayerInfo. But then checkState wants the timeline to be empty? Passing onto @marcbaechinger who introduced the check in https://github.com/androidx/media/commit/dee83cc7db73e5a07b4addc9325810643c9ec13d. Perhaps the problem is in the mediaItemIndex instead and we should add an error message to that checkState for easier debugging.
Thank you for your reply. We will address the issue based on the provided solution
Julia @.***> 于2025年11月4日周二 19:30写道:
oceanjules left a comment (androidx/media#2877) https://github.com/androidx/media/issues/2877#issuecomment-3485509221
I think your failure occured here:
https://github.com/androidx/media/blob/bfe5930f7f29c6492d60e3d01a90abd3c138b615/libraries/session/src/main/java/androidx/media3/session/PlayerInfo.java#L380-L384
I'm assuming that when you replace the media items, you trigger MediaSessionImpl.PlayerListener.onTimelineChanged -> session.playerInfo.copyWithTimelineAndSessionPositionInfo which then sets the timeline AND builds the PlayerInfo. But then checkState wants the timeline to be empty? Passing onto @marcbaechinger https://github.com/marcbaechinger who introduced the check in dee83cc https://github.com/androidx/media/commit/dee83cc7db73e5a07b4addc9325810643c9ec13d. Perhaps the problem is in the mediaItemIndex instead and we should add an error message to that checkState for easier debugging.
— Reply to this email directly, view it on GitHub https://github.com/androidx/media/issues/2877#issuecomment-3485509221, or unsubscribe https://github.com/notifications/unsubscribe-auth/BR64W7OX7FZHN6DAW3B5TBL33CE5ZAVCNFSM6AAAAACLBQLIMWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTIOBVGUYDSMRSGE . You are receiving this because you authored the thread.Message ID: @.***>