Request & release audio focus during voice recordings playback
This commit is contained in:
parent
536e78e98e
commit
a9daf53d69
3 changed files with 71 additions and 0 deletions
|
@ -26,6 +26,7 @@ import android.text.Spanned
|
||||||
import android.text.style.UnderlineSpan
|
import android.text.style.UnderlineSpan
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.media.AudioFocusRequestCompat
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
@ -73,6 +74,7 @@ class ChatMessageContentData(
|
||||||
val formattedDuration = MutableLiveData<String>()
|
val formattedDuration = MutableLiveData<String>()
|
||||||
val voiceRecordPlayingPosition = MutableLiveData<Int>()
|
val voiceRecordPlayingPosition = MutableLiveData<Int>()
|
||||||
val isVoiceRecordPlaying = MutableLiveData<Boolean>()
|
val isVoiceRecordPlaying = MutableLiveData<Boolean>()
|
||||||
|
var voiceRecordPlayingAudioFocusRequest: AudioFocusRequestCompat? = null
|
||||||
|
|
||||||
val isAlone: Boolean
|
val isAlone: Boolean
|
||||||
get() {
|
get() {
|
||||||
|
@ -257,6 +259,11 @@ class ChatMessageContentData(
|
||||||
initVoiceRecordPlayer()
|
initVoiceRecordPlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (voiceRecordPlayingAudioFocusRequest == null) {
|
||||||
|
voiceRecordPlayingAudioFocusRequest = AppUtils.acquireAudioFocusForVoiceRecording(
|
||||||
|
coreContext.context
|
||||||
|
)
|
||||||
|
}
|
||||||
voiceRecordingPlayer.start()
|
voiceRecordingPlayer.start()
|
||||||
isVoiceRecordPlaying.value = true
|
isVoiceRecordPlaying.value = true
|
||||||
tickerFlow().onEach {
|
tickerFlow().onEach {
|
||||||
|
@ -269,6 +276,13 @@ class ChatMessageContentData(
|
||||||
if (!isPlayerClosed()) {
|
if (!isPlayerClosed()) {
|
||||||
voiceRecordingPlayer.pause()
|
voiceRecordingPlayer.pause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val request = voiceRecordPlayingAudioFocusRequest
|
||||||
|
if (request != null) {
|
||||||
|
AppUtils.releaseAudioFocusForVoiceRecording(coreContext.context, request)
|
||||||
|
voiceRecordPlayingAudioFocusRequest = null
|
||||||
|
}
|
||||||
|
|
||||||
isVoiceRecordPlaying.value = false
|
isVoiceRecordPlaying.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import android.widget.Toast
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.media.AudioFocusRequestCompat
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -89,6 +90,8 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
|
||||||
|
|
||||||
val voiceRecordPlayingPosition = MutableLiveData<Int>()
|
val voiceRecordPlayingPosition = MutableLiveData<Int>()
|
||||||
|
|
||||||
|
var voiceRecordPlayingAudioFocusRequest: AudioFocusRequestCompat? = null
|
||||||
|
|
||||||
private lateinit var voiceRecordingPlayer: Player
|
private lateinit var voiceRecordingPlayer: Player
|
||||||
private val playerListener = PlayerListener {
|
private val playerListener = PlayerListener {
|
||||||
Log.i("[Chat Message Sending] End of file reached")
|
Log.i("[Chat Message Sending] End of file reached")
|
||||||
|
@ -352,6 +355,12 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
|
||||||
initVoiceRecordPlayer()
|
initVoiceRecordPlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (voiceRecordPlayingAudioFocusRequest == null) {
|
||||||
|
voiceRecordPlayingAudioFocusRequest = AppUtils.acquireAudioFocusForVoiceRecording(
|
||||||
|
coreContext.context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
voiceRecordingPlayer.start()
|
voiceRecordingPlayer.start()
|
||||||
isPlayingVoiceRecording.value = true
|
isPlayingVoiceRecording.value = true
|
||||||
|
|
||||||
|
@ -366,6 +375,12 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
|
||||||
voiceRecordingPlayer.pause()
|
voiceRecordingPlayer.pause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val request = voiceRecordPlayingAudioFocusRequest
|
||||||
|
if (request != null) {
|
||||||
|
AppUtils.releaseAudioFocusForVoiceRecording(coreContext.context, request)
|
||||||
|
voiceRecordPlayingAudioFocusRequest = null
|
||||||
|
}
|
||||||
|
|
||||||
isPlayingVoiceRecording.value = false
|
isPlayingVoiceRecording.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,6 +430,13 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
|
||||||
voiceRecordPlayingPosition.value = 0
|
voiceRecordPlayingPosition.value = 0
|
||||||
voiceRecordingPlayer.close()
|
voiceRecordingPlayer.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val request = voiceRecordPlayingAudioFocusRequest
|
||||||
|
if (request != null) {
|
||||||
|
AppUtils.releaseAudioFocusForVoiceRecording(coreContext.context, request)
|
||||||
|
voiceRecordPlayingAudioFocusRequest = null
|
||||||
|
}
|
||||||
|
|
||||||
isPlayingVoiceRecording.value = false
|
isPlayingVoiceRecording.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,9 @@ import android.text.format.Formatter.formatShortFileSize
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.emoji.text.EmojiCompat
|
import androidx.emoji.text.EmojiCompat
|
||||||
|
import androidx.media.AudioAttributesCompat
|
||||||
|
import androidx.media.AudioFocusRequestCompat
|
||||||
|
import androidx.media.AudioManagerCompat
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -146,5 +149,37 @@ class AppUtils {
|
||||||
Log.i("[Media Volume] Current value is $currentVolume, max value is $maxVolume")
|
Log.i("[Media Volume] Current value is $currentVolume, max value is $maxVolume")
|
||||||
return currentVolume <= maxVolume * 0.5
|
return currentVolume <= maxVolume * 0.5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun acquireAudioFocusForVoiceRecording(context: Context): AudioFocusRequestCompat {
|
||||||
|
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
val audioAttrs = AudioAttributesCompat.Builder()
|
||||||
|
.setUsage(AudioAttributesCompat.USAGE_MEDIA)
|
||||||
|
.setContentType(AudioAttributesCompat.CONTENT_TYPE_SPEECH)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request =
|
||||||
|
AudioFocusRequestCompat.Builder(AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
|
||||||
|
.setAudioAttributes(audioAttrs)
|
||||||
|
.setOnAudioFocusChangeListener { }
|
||||||
|
.build()
|
||||||
|
when (AudioManagerCompat.requestAudioFocus(audioManager, request)) {
|
||||||
|
AudioManager.AUDIOFOCUS_REQUEST_GRANTED -> {
|
||||||
|
Log.i("[Audio Focus] Voice recording audio focus request granted")
|
||||||
|
}
|
||||||
|
AudioManager.AUDIOFOCUS_REQUEST_FAILED -> {
|
||||||
|
Log.w("[Audio Focus] Voice recording audio focus request failed")
|
||||||
|
}
|
||||||
|
AudioManager.AUDIOFOCUS_REQUEST_DELAYED -> {
|
||||||
|
Log.w("[Audio Focus] Voice recording audio focus request delayed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
fun releaseAudioFocusForVoiceRecording(context: Context, request: AudioFocusRequestCompat) {
|
||||||
|
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
AudioManagerCompat.abandonAudioFocusRequest(audioManager, request)
|
||||||
|
Log.i("[Audio Focus] Voice recording audio focus request abandoned")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue