Skip to content

Instantly share code, notes, and snippets.

@esafirm
Last active February 3, 2026 08:28
Show Gist options
  • Select an option

  • Save esafirm/4d10c576c7c5a5ed4bf8130d19811744 to your computer and use it in GitHub Desktop.

Select an option

Save esafirm/4d10c576c7c5a5ed4bf8130d19811744 to your computer and use it in GitHub Desktop.
Easy way to simulate a player exception in ExoPlayer
package com.bandlab.media.player
import androidx.media3.common.MediaItem
import androidx.media3.datasource.TransferListener
import androidx.media3.exoplayer.analytics.PlayerId
import androidx.media3.exoplayer.source.MediaSource
import java.util.Random
class FirstFailureMediaSourceFactory(
private val delegate: MediaSource.Factory,
) : MediaSource.Factory by delegate {
override fun createMediaSource(mediaItem: MediaItem): MediaSource {
val originalSource = delegate.createMediaSource(mediaItem)
return FirstFailureMediaSource(originalSource)
}
}
object MediaSourceFailureController {
private var counter: Int = 0
fun shouldError(): Boolean {
counter++
if (counter >= 5) {
counter = 0
return true
}
return false
}
}
private class FirstFailureMediaSource(private val delegate: MediaSource) : MediaSource by delegate {
override fun prepareSource(
caller: MediaSource.MediaSourceCaller,
mediaTransferListener: TransferListener?,
playerId: PlayerId,
) {
if (MediaSourceFailureController.shouldError()) {
// We throw immediately when the player tries to prepare the source
// This is caught by ExoPlayerImplInternal and wrapped as TYPE_UNEXPECTED
throw NullPointerException("androidx.media3.decoder.mpeghaudio.MpeghAudioSink")
} else {
delegate.prepareSource(caller, mediaTransferListener, playerId)
}
}
}

Just set it as media source factory

ExoPlayer.Builder(context)
  .setMediaSourceFactory(FirstFailureMediaFactory(realMediaSourceFactory))
  ....
  .build()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment