MediaController.addListener.onMediaItemTransition() may incorrect call
@tonihei is already working on this.
Since Jun 23, 2022.
- Dominant language
- Java
- Stars
- 3k
- Forks
- 955
- Avg merge
- 12d 14h
- Merged PRs (30d)
- 2
Description
Media3 Version
1.0.0-beta01
Devices that reproduce the issue
Samsung galaxy note 10 5G running Android 11
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
- In service LibrarySessionCallback.onAddMediaItems() method like this, just transfer uri to
MediaItem:
override fun onAddMediaItems(
mediaSession: MediaSession,
controller: MediaSession.ControllerInfo,
mediaItems: MutableList<MediaItem>
): ListenableFuture<MutableList<MediaItem>> {
return MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()).submit<MutableList<MediaItem>> {
val infoList = contentResolver.query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
arrayOf(
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.ARTIST,
),
"${MediaStore.Audio.Media.DATA} IN (${mediaItems.joinToString { "'${it.requestMetadata.mediaUri.toString()}'" }})",
null,
null
)?.use { cursor ->
val columnIndexOfId = cursor.getColumnIndex(MediaStore.Audio.Media._ID)
val columnIndexOfData = cursor.getColumnIndex(MediaStore.Audio.Media.DATA)
val columnIndexOfTitle = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)
val columnIndexOfDuration = cursor.getColumnIndex(MediaStore.Audio.Media.DURATION)
val columnIndexOfArtist = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)
val list = mutableListOf<Array<String>>()
while (cursor.moveToNext()) {
list.add(
arrayOf(
cursor.getLong(columnIndexOfId).toString(),
cursor.getString(columnIndexOfData).orEmpty(),
cursor.getString(columnIndexOfTitle).orEmpty(),
cursor.getLong(columnIndexOfDuration).formatToVideoDuration(),
cursor.getString(columnIndexOfArtist).orEmpty(),
)
)
}
list
} ?: return@submit mutableListOf()
val resultItems = mediaItems.map { mediaItem ->
val infoArray = infoList.find { it[1] == mediaItem.requestMetadata.mediaUri.toString() } ?: return@map null
val metadataBuilder = MediaMetadata.Builder().apply {
setTitle(infoArray[2])
setDurationStr(infoArray[3])
setArtist(infoArray[4])
setFolderType(MediaMetadata.FOLDER_TYPE_NONE)
setIsPlayable(true)
}
mediaItem.buildUpon()
.setMediaMetadata(metadataBuilder.build())
.setMediaId(infoArray[0])
.setUri(mediaItem.requestMetadata.mediaUri)
.build()
}.filterNotNull().toMutableList()
resultItems
}
}
- Initialize controller in
Activity.onStart(), setMediaItemlist in controller future`s listener:
private fun initController() {
vm.controllerFuture =
MediaController.Builder(
this,
SessionToken(this, ComponentName(this, AudioPlayerService::class.java))
).buildAsync()
vm.controllerFuture.addListener(
{
val controller = vm.controller ?: return@addListener
controller.addListener(object : Player.Listener {
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
// code A
}
})
val mediaItems = uriList.map { uriString ->
MediaItem.Builder()
.setRequestMetadata(
MediaItem.RequestMetadata.Builder()
.setMediaUri(Uri.parse(uriString))
.build()
)
.build()
}
// code B
controller.setMediaItems(mediaItems)
},
MoreExecutors.directExecutor()
)
}
-
when code B is call automaticaly or by hand, a problem occured.
-
when
controller.setMediaItems(mediaItems)called, thecode Awill be call immediately, the given mediaItem paremeter not converted byonAddMediaItemscallback, themonAddMediaItemshas been called, and thencode Abe called again, the mediaItem is converted byonAddMediaItems.
Expected result
When controller.setMediaItems(mediaItems)(code B) has been called , the method call order that I except is:
MediaLibrarySession.Callback.onAddMediaItems()onMediaItemTransition(mediaItem, reason)has been set bycontroller.addListener(), and given mediaItem is converted byMediaLibrarySession.Callback.onAddMediaItems().
Actual result
onMediaItemTransition(mediaItem, reason)has been set bycontroller.addListener(), and given mediaItem is not converted byMediaLibrarySession.Callback.onAddMediaItems().MediaLibrarySession.Callback.onAddMediaItems()onMediaItemTransition(mediaItem, reason)has been set bycontroller.addListener(), and given mediaItem is converted byMediaLibrarySession.Callback.onAddMediaItems()now.
PS: when I set a Listener to ExoPlayer instance in service, it's onMediaItemTransition() method has called as I expected. So different behaviors exist between MediaController and ExoPlayer
This is the log I print manually, after controller.setMediaItems(mediaItems) called, may be useful.
2022-06-21 17:10:17.293 12071-12071/myPackageName D/Log-to-File: Thread: main
├ myPackageName.ui.player.audio.AudioPlayerViewModel$setController$1.onMediaItemTransition(AudioPlayerViewModel.kt:154)
├ androidx.media3.session.MediaControllerImplBase.lambda$updatePlayerInfo$46(MediaControllerImplBase.java:2114)
├ androidx.media3.session.MediaControllerImplBase$$ExternalSyntheticLambda41.invoke(Unknown Source:6)
├ androidx.media3.common.util.ListenerSet$ListenerHolder.invoke(ListenerSet.java:283)
├ androidx.media3.common.util.ListenerSet.lambda$queueEvent$0(ListenerSet.java:192)
├ androidx.media3.common.util.ListenerSet$$ExternalSyntheticLambda1.run(Unknown Source:6)
├ androidx.media3.common.util.ListenerSet.flushEvents(ListenerSet.java:213)
├ androidx.media3.session.MediaControllerImplBase.updatePlayerInfo(MediaControllerImplBase.java:2154)
├ androidx.media3.session.MediaControllerImplBase.setMediaItemsInternal(MediaControllerImplBase.java:1924)
├ androidx.media3.session.MediaControllerImplBase.setMediaItems(MediaControllerImplBase.java:931)
├ androidx.media3.session.MediaController.setMediaItems(MediaController.java:984)
├ myPackageName.ui.player.audio.AudioPlayerActivity.setMediaItemsAndPlay(AudioPlayerActivity.kt:266)
├ myPackageName.ui.player.audio.AudioPlayerActivity.access$setMediaItemsAndPlay(AudioPlayerActivity.kt:101)
├ myPackageName.ui.player.audio.AudioPlayerActivity$content$1$1$1.invoke(AudioPlayerActivity.kt:157)
├ myPackageName.ui.player.audio.AudioPlayerActivity$content$1$1$1.invoke(AudioPlayerActivity.kt:156)
├ myPackageName.ui.player.audio.AudioPlayerActivityKt$AudioPlayerScreen$1$1$4.invoke(AudioPlayerActivity.kt:303)
├ myPackageName.ui.player.audio.AudioPlayerActivityKt$AudioPlayerScreen$1$1$4.invoke(AudioPlayerActivity.kt:295)
├ myPackageName.utils.popup.MenuPopupWithTextAndIconKt$MenuPopupWithTextAndIcon$1$1$1$1.invoke(MenuPopupWithTextAndIcon.kt:96)
├ myPackageName.utils.popup.MenuPopupWithTextAndIconKt$MenuPopupWithTextAndIcon$1$1$1$1.invoke(MenuPopupWithTextAndIcon.kt:96)
└ androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$2.invoke-k-4lQ0M(Clickable.kt:153)
**// Here is called by controller's onMediaItemTransition()**
onMediaItemTransition: title=null mediaId=null /storage/emulated/0/Music/好多首歌/大島ミチル - Patema Inverse-copy6-copy-copy.mp3 reason=3
2022-06-21 17:10:17.385 12071-12071/myPackageName D/Log-to-File: Thread: main
├ myPackageName.ui.player.audio.AudioPlayerService$librarySessionCallback$1.onPlayerCommandRequest(AudioPlayerService.kt:213)
├ androidx.media3.session.MediaSessionImpl.onPlayerCommandRequestOnHandler(MediaSessionImpl.java:447)
├ androidx.media3.session.MediaSessionStub.lambda$getSessionTaskWithPlayerCommandRunnable$4$androidx-media3-session-MediaSessionStub(MediaSessionStub.java:261)
├ androidx.media3.session.MediaSessionStub$$ExternalSyntheticLambda71.run(Unknown Source:14)
├ androidx.media3.session.MediaSessionStub.lambda$flushCommandQueue$67(MediaSessionStub.java:1460)
├ androidx.media3.session.MediaSessionStub$$ExternalSyntheticLambda78.run(Unknown Source:2)
├ androidx.media3.common.util.Util.postOrRun(Util.java:548)
├ androidx.media3.session.MediaSessionStub.flushCommandQueue(MediaSessionStub.java:1454)
├ androidx.media3.session.MediaControllerImplBase$FlushCommandQueueHandler.handleMessage(MediaControllerImplBase.java:3059)
├ android.os.Handler.dispatchMessage(Handler.java:106)
├ android.os.Looper.loop(Looper.java:246)
├ android.app.ActivityThread.main(ActivityThread.java:8653)
├ java.lang.reflect.Method.invoke(Native Method)
├ com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
└ com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
onPlayerCommandRequest: playerCommand=20
2022-06-21 17:10:17.546 12071-13653/myPackageName D/Log-to-File: Thread: pool-13-thread-1
├ myPackageName.ui.player.audio.AudioPlayerService$librarySessionCallback$1.onAddMediaItems$lambda-6(AudioPlayerService.kt:192)
├ myPackageName.ui.player.audio.AudioPlayerService$librarySessionCallback$1.$r8$lambda$dZTOHF_a25TC4PIQE_k1kOcWRAE(Unknown Source:0)
├ myPackageName.ui.player.audio.AudioPlayerService$librarySessionCallback$1$$ExternalSyntheticLambda0.call(Unknown Source:4)
├ com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:131)
├ com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:74)
├ com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:82)
├ java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
├ java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
└ java.lang.Thread.run(Thread.java:923)
onAddMediaItems: listSize=1536
2022-06-21 17:10:17.724 12071-12071/myPackageName D/Log-to-File: Thread: main
├ myPackageName.ui.player.audio.AudioPlayerService$initSessionAndPlayer$1.onMediaItemTransition(AudioPlayerService.kt:285)
├ androidx.media3.exoplayer.ExoPlayerImpl.lambda$updatePlaybackInfo$14(ExoPlayerImpl.java:1890)
├ androidx.media3.exoplayer.ExoPlayerImpl$$ExternalSyntheticLambda25.invoke(Unknown Source:6)
├ androidx.media3.common.util.ListenerSet$ListenerHolder.invoke(ListenerSet.java:283)
├ androidx.media3.common.util.ListenerSet.lambda$queueEvent$0(ListenerSet.java:192)
├ androidx.media3.common.util.ListenerSet$$ExternalSyntheticLambda1.run(Unknown Source:6)
├ androidx.media3.common.util.ListenerSet.flushEvents(ListenerSet.java:213)
├ androidx.media3.exoplayer.ExoPlayerImpl.updatePlaybackInfo(ExoPlayerImpl.java:1963)
├ androidx.media3.exoplayer.ExoPlayerImpl.setMediaSourcesInternal(ExoPlayerImpl.java:2175)
├ androidx.media3.exoplayer.ExoPlayerImpl.setMediaSources(ExoPlayerImpl.java:605)
├ androidx.media3.exoplayer.ExoPlayerImpl.setMediaItems(ExoPlayerImpl.java:563)
├ androidx.media3.common.ForwardingPlayer.setMediaItems(ForwardingPlayer.java:76)
├ androidx.media3.session.PlayerWrapper.setMediaItems(PlayerWrapper.java:389)
├ androidx.media3.session.MediaSessionStub.lambda$setMediaItemsWithStartIndex$36(MediaSessionStub.java:1011)
├ androidx.media3.session.MediaSessionStub$$ExternalSyntheticLambda22.run(Unknown Source:4)
├ androidx.media3.session.MediaSessionStub.lambda$handleMediaItemsWhenReady$1(MediaSessionStub.java:164)
├ androidx.media3.session.MediaSessionStub$$ExternalSyntheticLambda70.run(Unknown Source:6)
├ android.os.Handler.handleCallback(Handler.java:938)
├ android.os.Handler.dispatchMessage(Handler.java:99)
└ android.os.Looper.loop(Looper.java:246)
**// Here is called by player's onMediaItemTransition()**
onMediaItemTransition: title=Patema Inverse mediaId=148808 /storage/emulated/0/Music/好多首歌/大島ミチル - Patema Inverse-copy6-copy-copy.mp3 reason=3
2022-06-21 17:10:18.132 12071-12071/myPackageName D/Log-to-File: Thread: main
├ myPackageName.ui.player.audio.AudioPlayerViewModel$setController$1.onMediaItemTransition(AudioPlayerViewModel.kt:154)
├ androidx.media3.session.MediaControllerImplBase.lambda$onPlayerInfoChanged$59$androidx-media3-session-MediaControllerImplBase(MediaControllerImplBase.java:2388)
├ androidx.media3.session.MediaControllerImplBase$$ExternalSyntheticLambda34.invoke(Unknown Source:6)
├ androidx.media3.common.util.ListenerSet$ListenerHolder.invoke(ListenerSet.java:283)
├ androidx.media3.common.util.ListenerSet.lambda$queueEvent$0(ListenerSet.java:192)
├ androidx.media3.common.util.ListenerSet$$ExternalSyntheticLambda1.run(Unknown Source:6)
├ androidx.media3.common.util.ListenerSet.flushEvents(ListenerSet.java:213)
├ androidx.media3.session.MediaControllerImplBase.onPlayerInfoChanged(MediaControllerImplBase.java:2520)
├ androidx.media3.session.MediaControllerStub.lambda$onPlayerInfoChanged$9(MediaControllerStub.java:180)
├ androidx.media3.session.MediaControllerStub$$ExternalSyntheticLambda12.run(Unknown Source:4)
├ androidx.media3.session.MediaControllerStub.lambda$dispatchControllerTaskOnHandler$13(MediaControllerStub.java:280)
├ androidx.media3.session.MediaControllerStub$$ExternalSyntheticLambda5.run(Unknown Source:4)
├ androidx.media3.common.util.Util.postOrRun(Util.java:548)
├ androidx.media3.session.MediaControllerStub.dispatchControllerTaskOnHandler(MediaControllerStub.java:272)
├ androidx.media3.session.MediaControllerStub.onPlayerInfoChanged(MediaControllerStub.java:178)
├ androidx.media3.session.MediaSessionStub$Controller2Cb.onPlayerInfoChanged(MediaSessionStub.java:1723)
├ androidx.media3.session.MediaSessionImpl.dispatchOnPlayerInfoChanged(MediaSessionImpl.java:400)
├ androidx.media3.session.MediaSessionImpl.access$600(MediaSessionImpl.java:79)
├ androidx.media3.session.MediaSessionImpl$PlayerInfoChangedHandler.handleMessage(MediaSessionImpl.java:1193)
└ android.os.Handler.dispatchMessage(Handler.java:106)
**// Here is called by controller's onMediaItemTransition()**
onMediaItemTransition: title=Patema Inverse 148808 /storage/emulated/0/Music/好多首歌/大島ミチル - Patema Inverse-copy6-copy-copy.mp3 reason=3
Media
Not applicable
Bug Report
- You will email the zip file produced by
adb bugreportto dev.exoplayer@gmail.com after filing this issue.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.