From a9daf53d69d26d0fee187693df5267013d2fe333 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 15 Jul 2021 13:49:51 +0200 Subject: [PATCH] Request & release audio focus during voice recordings playback --- .../main/chat/data/ChatMessageContentData.kt | 14 ++++++++ .../viewmodels/ChatMessageSendingViewModel.kt | 22 ++++++++++++ .../main/java/org/linphone/utils/AppUtils.kt | 35 +++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt index a9f390771..8c2be03cc 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/data/ChatMessageContentData.kt @@ -26,6 +26,7 @@ import android.text.Spanned import android.text.style.UnderlineSpan import android.widget.Toast import androidx.lifecycle.MutableLiveData +import androidx.media.AudioFocusRequestCompat import java.text.SimpleDateFormat import java.util.* import kotlinx.coroutines.* @@ -73,6 +74,7 @@ class ChatMessageContentData( val formattedDuration = MutableLiveData() val voiceRecordPlayingPosition = MutableLiveData() val isVoiceRecordPlaying = MutableLiveData() + var voiceRecordPlayingAudioFocusRequest: AudioFocusRequestCompat? = null val isAlone: Boolean get() { @@ -257,6 +259,11 @@ class ChatMessageContentData( initVoiceRecordPlayer() } + if (voiceRecordPlayingAudioFocusRequest == null) { + voiceRecordPlayingAudioFocusRequest = AppUtils.acquireAudioFocusForVoiceRecording( + coreContext.context + ) + } voiceRecordingPlayer.start() isVoiceRecordPlaying.value = true tickerFlow().onEach { @@ -269,6 +276,13 @@ class ChatMessageContentData( if (!isPlayerClosed()) { voiceRecordingPlayer.pause() } + + val request = voiceRecordPlayingAudioFocusRequest + if (request != null) { + AppUtils.releaseAudioFocusForVoiceRecording(coreContext.context, request) + voiceRecordPlayingAudioFocusRequest = null + } + isVoiceRecordPlaying.value = false } diff --git a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt index 8282f374b..ec192b441 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/viewmodels/ChatMessageSendingViewModel.kt @@ -23,6 +23,7 @@ import android.widget.Toast import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import androidx.media.AudioFocusRequestCompat import java.io.File import java.text.SimpleDateFormat import java.util.* @@ -89,6 +90,8 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() val voiceRecordPlayingPosition = MutableLiveData() + var voiceRecordPlayingAudioFocusRequest: AudioFocusRequestCompat? = null + private lateinit var voiceRecordingPlayer: Player private val playerListener = PlayerListener { Log.i("[Chat Message Sending] End of file reached") @@ -352,6 +355,12 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() initVoiceRecordPlayer() } + if (voiceRecordPlayingAudioFocusRequest == null) { + voiceRecordPlayingAudioFocusRequest = AppUtils.acquireAudioFocusForVoiceRecording( + coreContext.context + ) + } + voiceRecordingPlayer.start() isPlayingVoiceRecording.value = true @@ -366,6 +375,12 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() voiceRecordingPlayer.pause() } + val request = voiceRecordPlayingAudioFocusRequest + if (request != null) { + AppUtils.releaseAudioFocusForVoiceRecording(coreContext.context, request) + voiceRecordPlayingAudioFocusRequest = null + } + isPlayingVoiceRecording.value = false } @@ -415,6 +430,13 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel() voiceRecordPlayingPosition.value = 0 voiceRecordingPlayer.close() } + + val request = voiceRecordPlayingAudioFocusRequest + if (request != null) { + AppUtils.releaseAudioFocusForVoiceRecording(coreContext.context, request) + voiceRecordPlayingAudioFocusRequest = null + } + isPlayingVoiceRecording.value = false } diff --git a/app/src/main/java/org/linphone/utils/AppUtils.kt b/app/src/main/java/org/linphone/utils/AppUtils.kt index 756936ea8..a2123ece9 100644 --- a/app/src/main/java/org/linphone/utils/AppUtils.kt +++ b/app/src/main/java/org/linphone/utils/AppUtils.kt @@ -29,6 +29,9 @@ import android.text.format.Formatter.formatShortFileSize import android.util.TypedValue import androidx.core.content.res.ResourcesCompat 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.LinearLayoutManager import java.util.* @@ -146,5 +149,37 @@ class AppUtils { Log.i("[Media Volume] Current value is $currentVolume, max value is $maxVolume") 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") + } } }