ExoPlayer.setPauseAtEndOfMediaItems(false) are not working in media3 1.9.0
@marcbaechinger is already working on this.
Since Jan 5, 2026.
- Dominant language
- Java
- Stars
- 3k
- Forks
- 955
- Avg merge
- 12d 14h
- Merged PRs (30d)
- 2
Description
Version
Media3 1.9.0
More version details
With Media3 v1.8.0 the function working fine, no sending pause -> play signal to Player.Listener.onIsPlayingChanged
With Media3 v1.9.0 it send the pause -> play signal to Player.Listener.onIsPlayingChanged
Devices that reproduce the issue
Poco x6 5G - android 15 (my personal device)
Devices that do not reproduce the issue
i have no idea
Reproducible in the demo app?
Not tested
Reproduction steps
Im using MediaSessionService, here my settup:
@UnstableApi
class TTSService : MediaSessionService() {
private val ttsManager by inject<TTSManager>()
private var audioFocusChangeListener =
AudioManager.OnAudioFocusChangeListener { focusChange ->
when (focusChange) {
AudioManager.AUDIOFOCUS_GAIN -> {
ttsManager.checkResume()
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
ttsManager.checkPause()
}
AudioManager.AUDIOFOCUS_LOSS -> {
ttsManager.checkPause()
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
ttsManager.checkPause()
}
}
}
private val playbackAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build()
private val focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
.setAudioAttributes(playbackAttributes)
.setAcceptsDelayedFocusGain(true)
.setOnAudioFocusChangeListener(audioFocusChangeListener)
.build()
private lateinit var audioManager: AudioManager
private var mediaSession: MediaSession? = null
private val customCommandStop = SessionCommand(ACTION_STOP, Bundle.EMPTY)
private val customCommandNext = SessionCommand(ACTION_NEXT, Bundle.EMPTY)
private val customCommandPrevious = SessionCommand(ACTION_PREVIOUS, Bundle.EMPTY)
override fun onCreate() {
super.onCreate()
val stopButton = CommandButton.Builder(CommandButton.ICON_STOP)
.setCustomIconResId(R.drawable.ic_notification_stop)
.setDisplayName("Stop")
.setSessionCommand(customCommandStop)
.build()
val nextButton = CommandButton.Builder(CommandButton.ICON_SKIP_FORWARD)
.setCustomIconResId(R.drawable.ic_notification_skip_to_next)
.setDisplayName("Next Chapter")
.setSessionCommand(customCommandNext)
.build()
val previousButton = CommandButton.Builder(CommandButton.ICON_SKIP_BACK)
.setCustomIconResId(R.drawable.ic_notification_skip_to_back)
.setDisplayName("Previous Chapter")
.setSessionCommand(customCommandPrevious)
.build()
val myAudioAttributes = androidx.media3.common.AudioAttributes.Builder()
.setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
.setUsage(C.USAGE_MEDIA)
.build()
val player = ExoPlayer.Builder(this)
.setAudioAttributes(myAudioAttributes, false)
.setHandleAudioBecomingNoisy(true)
.setPauseAtEndOfMediaItems(false)
.build()
.apply {
repeatMode = Player.REPEAT_MODE_ALL
shuffleModeEnabled = true
}
val forwardingPlayer = object : ForwardingPlayer(player) {
override fun getAvailableCommands(): Player.Commands {
return super.getAvailableCommands()
.buildUpon()
.remove(COMMAND_SEEK_TO_NEXT)
.remove(COMMAND_SEEK_TO_PREVIOUS)
.remove(COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)
.build()
}
}
mediaSession = MediaSession.Builder(this, forwardingPlayer)
.setCallback(MyCallback())
.setCustomLayout(
ImmutableList.of(previousButton, nextButton, stopButton)
)
.build()
audioManager = getSystemService(AUDIO_SERVICE) as AudioManager
audioManager.requestAudioFocus(focusRequest)
}
override fun onDestroy() {
mediaSession?.run {
player.release()
release()
mediaSession = null
}
audioManager.abandonAudioFocusRequest(focusRequest)
super.onDestroy()
}
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? {
return mediaSession
}
override fun onTaskRemoved(rootIntent: Intent?) {
stopSelf()
}
private inner class MyCallback : MediaSession.Callback {
override fun onConnect(
session: MediaSession,
controller: MediaSession.ControllerInfo
): MediaSession.ConnectionResult {
return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
.setAvailablePlayerCommands(
MediaSession.ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon()
.remove(Player.COMMAND_SEEK_TO_NEXT)
.remove(Player.COMMAND_SEEK_TO_NEXT_MEDIA_ITEM)
.remove(Player.COMMAND_SEEK_TO_PREVIOUS)
.remove(Player.COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM)
.remove(Player.COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM)
.build()
)
.setAvailableSessionCommands(
MediaSession.ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon()
.add(customCommandPrevious)
.add(customCommandNext)
.add(customCommandStop)
.build()
)
.build()
}
override fun onCustomCommand(
session: MediaSession,
controller: MediaSession.ControllerInfo,
customCommand: SessionCommand,
args: Bundle
): ListenableFuture<SessionResult> {
return when (customCommand.customAction) {
ACTION_STOP -> {
ttsManager.stopReading(true)
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
}
ACTION_NEXT -> {
if (ttsManager.getIsTTSActivated()) {
ttsManager.checkPlayNextChapter()
} else {
mediaSession?.run {
player.seekToNextMediaItem()
}
}
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
}
ACTION_PREVIOUS -> {
if (ttsManager.getIsTTSActivated()) {
ttsManager.checkPlayPreviousChapter()
} else {
mediaSession?.run {
player.seekToPreviousMediaItem()
}
}
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
}
else -> {
super.onCustomCommand(session, controller, customCommand, args)
}
}
}
}
companion object {
const val ACTION_STOP = "ACTION_STOP"
const val ACTION_NEXT = "ACTION_NEXT"
const val ACTION_PREVIOUS = "ACTION_PREVIOUS"
}
}
and i have another Player.Listener in another class that override the onIsPlayingChanged function.
Expected result
With Media3 v1.8.0, i didnt saw any Pause->Play update on the default media notification when player reach the end of a media item. And my Player.Listener are not receive any signal (which is what i expected)
Actual result
With Media3 v1.9.0, i saw Pause->Play update on the default media notification when player reach the end of a media item. And my Player.Listener are receiving the Pause->Play signal (which break my current code logic)
Media
Not applicable
Bug Report
- You will email the zip file produced by
adb bugreportto android-media-github@google.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.