Skip to content

Instantly share code, notes, and snippets.

@nazmulidris
Created March 9, 2018 01:20
Show Gist options
  • Save nazmulidris/a369cf3265676c7991e9803dc4791e0e to your computer and use it in GitHub Desktop.
Save nazmulidris/a369cf3265676c7991e9803dc4791e0e to your computer and use it in GitHub Desktop.
class AudioFocusWrapper(private val audioAttributes: AudioAttributesCompat,
private val audioManager: AudioManager,
private val player: SimpleExoPlayer) : ExoPlayer by player, AnkoLogger {
private var shouldPlayWhenReady = false
private val audioFocusListener =
AudioManager.OnAudioFocusChangeListener { focusChange ->
when (focusChange) {
AudioManager.AUDIOFOCUS_GAIN -> {
if (shouldPlayWhenReady || player.playWhenReady) {
player.playWhenReady = true
player.volume = MEDIA_VOLUME_DEFAULT
}
shouldPlayWhenReady = false
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
if (player.playWhenReady) {
player.volume = MEDIA_VOLUME_DUCK
}
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
shouldPlayWhenReady = player.playWhenReady
player.playWhenReady = false
}
AudioManager.AUDIOFOCUS_LOSS -> {
abandonAudioFocus()
}
}
}
@get:RequiresApi(Build.VERSION_CODES.O)
private val audioFocusRequest by lazy { buildFocusRequest() }
override fun setPlayWhenReady(playWhenReady: Boolean) {
if (playWhenReady) requestAudioFocus() else abandonAudioFocus()
}
private fun requestAudioFocus() {
val result = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
requestAudioFocusOreo()
} else {
@Suppress("deprecation")
audioManager.requestAudioFocus(audioFocusListener,
audioAttributes.legacyStreamType,
AudioManager.AUDIOFOCUS_GAIN)
}
// Call the listener whenever focus is granted - even the first time!
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
shouldPlayWhenReady = true
audioFocusListener.onAudioFocusChange(AudioManager.AUDIOFOCUS_GAIN)
} else {
warn { "Playback not started: Audio focus request denied" }
}
}
private fun abandonAudioFocus() {
player.playWhenReady = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
abandonAudioFocusOreo()
} else {
@Suppress("deprecation")
audioManager.abandonAudioFocus(audioFocusListener)
}
}
@RequiresApi(Build.VERSION_CODES.O)
private fun requestAudioFocusOreo(): Int =
audioManager.requestAudioFocus(audioFocusRequest)
@RequiresApi(Build.VERSION_CODES.O)
private fun abandonAudioFocusOreo() =
audioManager.abandonAudioFocusRequest(audioFocusRequest)
@TargetApi(Build.VERSION_CODES.O)
private fun buildFocusRequest(): AudioFocusRequest =
AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
.setAudioAttributes(
audioAttributes.unwrap() as? AudioAttributes)
.setOnAudioFocusChangeListener(audioFocusListener)
.build()
}
private const val MEDIA_VOLUME_DEFAULT = 1.0f
private const val MEDIA_VOLUME_DUCK = 0.2f
Finally, to use this instead of a SimpleExoPlayer here’s what the PlayerHolder class (that you’ve seen in the previous parts of this series of articles) looks like.
class PlayerHolder(val context: Context,
val playerState: PlayerState,
val playerView: PlayerView) : AnkoLogger {
val audioFocusPlayer: ExoPlayer
// Create the player instance.
init {
val audioManager =
context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
val audioAttributes = AudioAttributesCompat.Builder()
.setContentType(AudioAttributesCompat.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributesCompat.USAGE_MEDIA)
.build()
audioFocusPlayer = AudioFocusWrapper(
audioAttributes,
audioManager,
ExoPlayerFactory.newSimpleInstance(
context, DefaultTrackSelector())
.apply { playerView.player = this }
)
info { "SimpleExoPlayer created" }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment