mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-19 11:39:42 +01:00
handle audio focus and becoming noisy
Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>
This commit is contained in:
parent
26f59c9a35
commit
91d5217b1e
@ -42,7 +42,9 @@ import android.database.Cursor
|
|||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.media.AudioFocusRequest
|
||||||
import android.media.AudioFormat
|
import android.media.AudioFormat
|
||||||
|
import android.media.AudioManager
|
||||||
import android.media.AudioRecord
|
import android.media.AudioRecord
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
import android.media.MediaRecorder
|
import android.media.MediaRecorder
|
||||||
@ -384,6 +386,8 @@ class ChatActivity :
|
|||||||
private var lastRecordMediaPosition: Int = 0
|
private var lastRecordMediaPosition: Int = 0
|
||||||
private var lastRecordedSeeked: Boolean = false
|
private var lastRecordedSeeked: Boolean = false
|
||||||
|
|
||||||
|
private val audioFocusChangeListener = getAudioFocusChangeListener()
|
||||||
|
|
||||||
private lateinit var participantPermissions: ParticipantPermissions
|
private lateinit var participantPermissions: ParticipantPermissions
|
||||||
|
|
||||||
private var videoURI: Uri? = null
|
private var videoURI: Uri? = null
|
||||||
@ -1099,7 +1103,9 @@ class ChatActivity :
|
|||||||
|
|
||||||
binding.messageInputView.micInputCloud.setOnClickListener {
|
binding.messageInputView.micInputCloud.setOnClickListener {
|
||||||
if (mediaRecorderState == MediaRecorderState.RECORDING) {
|
if (mediaRecorderState == MediaRecorderState.RECORDING) {
|
||||||
recorder?.stop()
|
audioFocusRequest(false) {
|
||||||
|
recorder?.stop()
|
||||||
|
}
|
||||||
mediaRecorderState = MediaRecorderState.INITIAL
|
mediaRecorderState = MediaRecorderState.INITIAL
|
||||||
stopMicInputRecordingAnimation()
|
stopMicInputRecordingAnimation()
|
||||||
showPreviewVoiceRecording(true)
|
showPreviewVoiceRecording(true)
|
||||||
@ -1328,8 +1334,10 @@ class ChatActivity :
|
|||||||
duration = it.duration.toLong()
|
duration = it.duration.toLong()
|
||||||
interpolator = LinearInterpolator()
|
interpolator = LinearInterpolator()
|
||||||
}
|
}
|
||||||
voicePreviewMediaPlayer!!.start()
|
audioFocusRequest(true) {
|
||||||
voicePreviewObjectAnimator!!.start()
|
voicePreviewMediaPlayer!!.start()
|
||||||
|
voicePreviewObjectAnimator!!.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setOnCompletionListener {
|
setOnCompletionListener {
|
||||||
@ -1343,15 +1351,19 @@ class ChatActivity :
|
|||||||
if (voicePreviewMediaPlayer == null) {
|
if (voicePreviewMediaPlayer == null) {
|
||||||
initPreviewVoiceRecording()
|
initPreviewVoiceRecording()
|
||||||
} else {
|
} else {
|
||||||
voicePreviewMediaPlayer!!.start()
|
audioFocusRequest(true) {
|
||||||
voicePreviewObjectAnimator!!.resume()
|
voicePreviewMediaPlayer!!.start()
|
||||||
|
voicePreviewObjectAnimator!!.resume()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pausePreviewVoicePlaying() {
|
private fun pausePreviewVoicePlaying() {
|
||||||
Log.d(TAG, "paused preview voice recording")
|
Log.d(TAG, "paused preview voice recording")
|
||||||
voicePreviewMediaPlayer!!.pause()
|
audioFocusRequest(false) {
|
||||||
voicePreviewObjectAnimator!!.pause()
|
voicePreviewMediaPlayer!!.pause()
|
||||||
|
voicePreviewObjectAnimator!!.pause()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopPreviewVoicePlaying() {
|
private fun stopPreviewVoicePlaying() {
|
||||||
@ -1361,9 +1373,11 @@ class ChatActivity :
|
|||||||
voicePreviewObjectAnimator!!.end()
|
voicePreviewObjectAnimator!!.end()
|
||||||
voicePreviewObjectAnimator = null
|
voicePreviewObjectAnimator = null
|
||||||
binding.messageInputView.seekBar.clearAnimation()
|
binding.messageInputView.seekBar.clearAnimation()
|
||||||
voicePreviewMediaPlayer!!.stop()
|
audioFocusRequest(false) {
|
||||||
voicePreviewMediaPlayer!!.release()
|
voicePreviewMediaPlayer!!.stop()
|
||||||
voicePreviewMediaPlayer = null
|
voicePreviewMediaPlayer!!.release()
|
||||||
|
voicePreviewMediaPlayer = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1817,6 +1831,56 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getAudioFocusChangeListener(): AudioManager.OnAudioFocusChangeListener {
|
||||||
|
return AudioManager.OnAudioFocusChangeListener { flag ->
|
||||||
|
when (flag) {
|
||||||
|
AudioManager.AUDIOFOCUS_LOSS -> {
|
||||||
|
if (isVoicePreviewPlaying) {
|
||||||
|
stopPreviewVoicePlaying()
|
||||||
|
}
|
||||||
|
if (currentlyPlayedVoiceMessage != null) {
|
||||||
|
stopMediaPlayer(currentlyPlayedVoiceMessage!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
|
||||||
|
if (isVoicePreviewPlaying) {
|
||||||
|
pausePreviewVoicePlaying()
|
||||||
|
}
|
||||||
|
if (currentlyPlayedVoiceMessage != null) {
|
||||||
|
pausePlayback(currentlyPlayedVoiceMessage!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun audioFocusRequest(shouldRequestFocus: Boolean, onGranted: () -> Unit) {
|
||||||
|
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||||
|
val duration = AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
|
||||||
|
|
||||||
|
val isGranted: Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val focusRequest = AudioFocusRequest.Builder(duration)
|
||||||
|
.setOnAudioFocusChangeListener(audioFocusChangeListener)
|
||||||
|
.build()
|
||||||
|
if (shouldRequestFocus) {
|
||||||
|
audioManager.requestAudioFocus(focusRequest)
|
||||||
|
} else {
|
||||||
|
audioManager.abandonAudioFocusRequest(focusRequest)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@Deprecated("This method was deprecated in API level 26.")
|
||||||
|
if (shouldRequestFocus) {
|
||||||
|
audioManager.requestAudioFocus(audioFocusChangeListener, AudioManager.STREAM_MUSIC, duration)
|
||||||
|
} else {
|
||||||
|
audioManager.abandonAudioFocus(audioFocusChangeListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isGranted == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||||
|
onGranted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun startPlayback(message: ChatMessage) {
|
private fun startPlayback(message: ChatMessage) {
|
||||||
if (!active) {
|
if (!active) {
|
||||||
// don't begin to play voice message if screen is not visible anymore.
|
// don't begin to play voice message if screen is not visible anymore.
|
||||||
@ -1830,8 +1894,9 @@ class ChatActivity :
|
|||||||
|
|
||||||
mediaPlayer?.let {
|
mediaPlayer?.let {
|
||||||
if (!it.isPlaying) {
|
if (!it.isPlaying) {
|
||||||
it.start()
|
audioFocusRequest(true) {
|
||||||
Log.d(TAG, "MediaPlayer has Started")
|
it.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaPlayerHandler = Handler()
|
mediaPlayerHandler = Handler()
|
||||||
@ -1866,8 +1931,9 @@ class ChatActivity :
|
|||||||
|
|
||||||
private fun pausePlayback(message: ChatMessage) {
|
private fun pausePlayback(message: ChatMessage) {
|
||||||
if (mediaPlayer!!.isPlaying) {
|
if (mediaPlayer!!.isPlaying) {
|
||||||
mediaPlayer!!.pause()
|
audioFocusRequest(false) {
|
||||||
Log.d(TAG, "MediaPlayer is paused")
|
mediaPlayer!!.pause()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message.isPlayingVoiceMessage = false
|
message.isPlayingVoiceMessage = false
|
||||||
@ -1925,7 +1991,9 @@ class ChatActivity :
|
|||||||
mediaPlayer?.let {
|
mediaPlayer?.let {
|
||||||
if (it.isPlaying) {
|
if (it.isPlaying) {
|
||||||
Log.d(TAG, "media player is stopped")
|
Log.d(TAG, "media player is stopped")
|
||||||
it.stop()
|
audioFocusRequest(false) {
|
||||||
|
it.stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
@ -2141,8 +2209,10 @@ class ChatActivity :
|
|||||||
private fun stopMicInputRecordingAnimation() {
|
private fun stopMicInputRecordingAnimation() {
|
||||||
if (micInputAudioRecordThread != null) {
|
if (micInputAudioRecordThread != null) {
|
||||||
Log.d(TAG, "Mic Animation Ended")
|
Log.d(TAG, "Mic Animation Ended")
|
||||||
micInputAudioRecorder.stop()
|
audioFocusRequest(false) {
|
||||||
micInputAudioRecorder.release()
|
micInputAudioRecorder.stop()
|
||||||
|
micInputAudioRecorder.release()
|
||||||
|
}
|
||||||
isMicInputAudioThreadRunning = false
|
isMicInputAudioThreadRunning = false
|
||||||
micInputAudioRecordThread = null
|
micInputAudioRecordThread = null
|
||||||
}
|
}
|
||||||
@ -2193,7 +2263,9 @@ class ChatActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
start()
|
audioFocusRequest(true) {
|
||||||
|
start()
|
||||||
|
}
|
||||||
mediaRecorderState = MediaRecorderState.RECORDING
|
mediaRecorderState = MediaRecorderState.RECORDING
|
||||||
Log.d(TAG, "recording started")
|
Log.d(TAG, "recording started")
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: IllegalStateException) {
|
||||||
@ -2234,8 +2306,10 @@ class ChatActivity :
|
|||||||
recorder?.apply {
|
recorder?.apply {
|
||||||
try {
|
try {
|
||||||
if (mediaRecorderState == MediaRecorderState.RECORDING) {
|
if (mediaRecorderState == MediaRecorderState.RECORDING) {
|
||||||
stop()
|
audioFocusRequest(false) {
|
||||||
reset()
|
stop()
|
||||||
|
reset()
|
||||||
|
}
|
||||||
mediaRecorderState = MediaRecorderState.INITIAL
|
mediaRecorderState = MediaRecorderState.INITIAL
|
||||||
Log.d(TAG, "stopped recorder")
|
Log.d(TAG, "stopped recorder")
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ import androidx.core.view.marginBottom
|
|||||||
import androidx.core.view.updateLayoutParams
|
import androidx.core.view.updateLayoutParams
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.media3.common.AudioAttributes
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
@ -165,7 +166,10 @@ class FullScreenMediaActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun initializePlayer() {
|
private fun initializePlayer() {
|
||||||
player = ExoPlayer.Builder(applicationContext).build()
|
player = ExoPlayer.Builder(applicationContext)
|
||||||
|
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
||||||
|
.setHandleAudioBecomingNoisy(true)
|
||||||
|
.build()
|
||||||
binding.playerView.player = player
|
binding.playerView.player = player
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,6 +206,7 @@ class FullScreenMediaActivity : AppCompatActivity() {
|
|||||||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||||
supportActionBar?.show()
|
supportActionBar?.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applyWindowInsets() {
|
private fun applyWindowInsets() {
|
||||||
val playerView = binding.playerView
|
val playerView = binding.playerView
|
||||||
val exoControls = playerView.findViewById<FrameLayout>(R.id.exo_bottom_bar)
|
val exoControls = playerView.findViewById<FrameLayout>(R.id.exo_bottom_bar)
|
||||||
|
Loading…
Reference in New Issue
Block a user