inject AudioFocusRequest.Builder and fix lint
Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
parent
2b44bbea8f
commit
b7e96ad0a7
@ -8,7 +8,6 @@ package com.nextcloud.client.media
|
||||
|
||||
import android.media.AudioFocusRequest
|
||||
import android.media.AudioManager
|
||||
import android.os.Build
|
||||
|
||||
/**
|
||||
* Wrapper around audio manager exposing simplified audio focus API and
|
||||
@ -19,45 +18,29 @@ import android.os.Build
|
||||
*/
|
||||
internal class AudioFocusManager(
|
||||
private val audioManger: AudioManager,
|
||||
private val onFocusChange: (AudioFocus) -> Unit
|
||||
private val onFocusChange: (AudioFocus) -> Unit,
|
||||
requestBuilder: AudioFocusRequest.Builder = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
|
||||
) {
|
||||
|
||||
private val focusListener = object : AudioManager.OnAudioFocusChangeListener {
|
||||
override fun onAudioFocusChange(focusChange: Int) {
|
||||
val focus = when (focusChange) {
|
||||
AudioManager.AUDIOFOCUS_GAIN -> AudioFocus.FOCUS
|
||||
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT -> AudioFocus.FOCUS
|
||||
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK -> AudioFocus.FOCUS
|
||||
AudioManager.AUDIOFOCUS_LOSS -> AudioFocus.LOST
|
||||
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> AudioFocus.LOST
|
||||
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> AudioFocus.DUCK
|
||||
else -> null
|
||||
}
|
||||
focus?.let { onFocusChange(it) }
|
||||
}
|
||||
}
|
||||
private var focusRequest: AudioFocusRequest? = null
|
||||
|
||||
init {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN).run {
|
||||
setWillPauseWhenDucked(true)
|
||||
setOnAudioFocusChangeListener(focusListener)
|
||||
}.build()
|
||||
private val focusListener = AudioManager.OnAudioFocusChangeListener { focusChange ->
|
||||
val focus = when (focusChange) {
|
||||
AudioManager.AUDIOFOCUS_GAIN,
|
||||
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
|
||||
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK -> AudioFocus.FOCUS
|
||||
AudioManager.AUDIOFOCUS_LOSS,
|
||||
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> AudioFocus.LOST
|
||||
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> AudioFocus.DUCK
|
||||
else -> null
|
||||
}
|
||||
focus?.let { onFocusChange(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Request audio focus. Focus is reported via callback.
|
||||
* If focus cannot be gained, lost of focus is reported.
|
||||
*/
|
||||
private val focusRequest = requestBuilder
|
||||
.setWillPauseWhenDucked(true)
|
||||
.setOnAudioFocusChangeListener(focusListener)
|
||||
.build()
|
||||
|
||||
fun requestFocus() {
|
||||
val requestResult = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
focusRequest?.let { audioManger.requestAudioFocus(it) }
|
||||
} else {
|
||||
audioManger.requestAudioFocus(focusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
|
||||
}
|
||||
|
||||
val requestResult = audioManger.requestAudioFocus(focusRequest)
|
||||
if (requestResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||
focusListener.onAudioFocusChange(AudioManager.AUDIOFOCUS_GAIN)
|
||||
} else {
|
||||
@ -65,17 +48,8 @@ internal class AudioFocusManager(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Release audio focus. Loss of focus is reported via callback.
|
||||
*/
|
||||
fun releaseFocus() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
focusRequest?.let {
|
||||
audioManger.abandonAudioFocusRequest(it)
|
||||
} ?: AudioManager.AUDIOFOCUS_REQUEST_FAILED
|
||||
} else {
|
||||
audioManger.abandonAudioFocus(focusListener)
|
||||
}
|
||||
audioManger.abandonAudioFocusRequest(focusRequest)
|
||||
focusListener.onAudioFocusChange(AudioManager.AUDIOFOCUS_LOSS)
|
||||
}
|
||||
}
|
||||
|
@ -10,50 +10,53 @@ import android.media.AudioFocusRequest
|
||||
import android.media.AudioManager
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentMatcher
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.argThat
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
class AudioFocusManagerTest {
|
||||
|
||||
private val audioManager = mock<AudioManager>()
|
||||
private val callback = mock<(AudioFocus) -> Unit>()
|
||||
private val audioManager: AudioManager = mock()
|
||||
private val callback: (AudioFocus) -> Unit = mock()
|
||||
private lateinit var audioFocusManager: AudioFocusManager
|
||||
|
||||
val audioRequestMatcher = object : ArgumentMatcher<AudioFocusRequest> {
|
||||
override fun matches(argument: AudioFocusRequest?): Boolean = true
|
||||
}
|
||||
private val builder: AudioFocusRequest.Builder = mock()
|
||||
private val focusRequest: AudioFocusRequest = mock()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
audioFocusManager = AudioFocusManager(audioManager, callback)
|
||||
whenever(audioManager.requestAudioFocus(any(), any(), any()))
|
||||
// Chain mock methods for the builder
|
||||
whenever(builder.setWillPauseWhenDucked(true)).thenReturn(builder)
|
||||
whenever(builder.setOnAudioFocusChangeListener(any())).thenReturn(builder)
|
||||
whenever(builder.build()).thenReturn(focusRequest)
|
||||
|
||||
audioFocusManager = AudioFocusManager(audioManager, callback, builder)
|
||||
|
||||
whenever(audioManager.requestAudioFocus(focusRequest))
|
||||
.thenReturn(AudioManager.AUDIOFOCUS_REQUEST_GRANTED)
|
||||
whenever(audioManager.abandonAudioFocusRequest(argThat(audioRequestMatcher)))
|
||||
.thenReturn(AudioManager.AUDIOFOCUS_REQUEST_GRANTED)
|
||||
whenever(audioManager.abandonAudioFocusRequest(any()))
|
||||
|
||||
whenever(audioManager.abandonAudioFocusRequest(focusRequest))
|
||||
.thenReturn(AudioManager.AUDIOFOCUS_REQUEST_GRANTED)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `acquiring focus triggers callback immediately`() {
|
||||
fun `requestFocus should invoke FOCUS callback when granted`() {
|
||||
audioFocusManager.requestFocus()
|
||||
verify(callback).invoke(AudioFocus.FOCUS)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `failing to acquire focus triggers callback immediately`() {
|
||||
whenever(audioManager.requestAudioFocus(any(), any(), any()))
|
||||
fun `requestFocus should invoke LOST callback when denied`() {
|
||||
whenever(audioManager.requestAudioFocus(focusRequest))
|
||||
.thenReturn(AudioManager.AUDIOFOCUS_REQUEST_FAILED)
|
||||
|
||||
audioFocusManager.requestFocus()
|
||||
verify(callback).invoke(AudioFocus.LOST)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `releasing focus triggers callback immediately`() {
|
||||
fun `releaseFocus should invoke LOST callback`() {
|
||||
audioFocusManager.releaseFocus()
|
||||
verify(callback).invoke(AudioFocus.LOST)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user