mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-25 22:45:41 +03:00
handle audio focus and becoming noisy
Signed-off-by: parneet-guraya <gurayaparneet@gmail.com>
This commit is contained in:
parent
26f59c9a35
commit
91d5217b1e
2 changed files with 100 additions and 21 deletions
|
@ -42,7 +42,9 @@ import android.database.Cursor
|
|||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.media.AudioFocusRequest
|
||||
import android.media.AudioFormat
|
||||
import android.media.AudioManager
|
||||
import android.media.AudioRecord
|
||||
import android.media.MediaPlayer
|
||||
import android.media.MediaRecorder
|
||||
|
@ -384,6 +386,8 @@ class ChatActivity :
|
|||
private var lastRecordMediaPosition: Int = 0
|
||||
private var lastRecordedSeeked: Boolean = false
|
||||
|
||||
private val audioFocusChangeListener = getAudioFocusChangeListener()
|
||||
|
||||
private lateinit var participantPermissions: ParticipantPermissions
|
||||
|
||||
private var videoURI: Uri? = null
|
||||
|
@ -1099,7 +1103,9 @@ class ChatActivity :
|
|||
|
||||
binding.messageInputView.micInputCloud.setOnClickListener {
|
||||
if (mediaRecorderState == MediaRecorderState.RECORDING) {
|
||||
recorder?.stop()
|
||||
audioFocusRequest(false) {
|
||||
recorder?.stop()
|
||||
}
|
||||
mediaRecorderState = MediaRecorderState.INITIAL
|
||||
stopMicInputRecordingAnimation()
|
||||
showPreviewVoiceRecording(true)
|
||||
|
@ -1328,8 +1334,10 @@ class ChatActivity :
|
|||
duration = it.duration.toLong()
|
||||
interpolator = LinearInterpolator()
|
||||
}
|
||||
voicePreviewMediaPlayer!!.start()
|
||||
voicePreviewObjectAnimator!!.start()
|
||||
audioFocusRequest(true) {
|
||||
voicePreviewMediaPlayer!!.start()
|
||||
voicePreviewObjectAnimator!!.start()
|
||||
}
|
||||
}
|
||||
|
||||
setOnCompletionListener {
|
||||
|
@ -1343,15 +1351,19 @@ class ChatActivity :
|
|||
if (voicePreviewMediaPlayer == null) {
|
||||
initPreviewVoiceRecording()
|
||||
} else {
|
||||
voicePreviewMediaPlayer!!.start()
|
||||
voicePreviewObjectAnimator!!.resume()
|
||||
audioFocusRequest(true) {
|
||||
voicePreviewMediaPlayer!!.start()
|
||||
voicePreviewObjectAnimator!!.resume()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun pausePreviewVoicePlaying() {
|
||||
Log.d(TAG, "paused preview voice recording")
|
||||
voicePreviewMediaPlayer!!.pause()
|
||||
voicePreviewObjectAnimator!!.pause()
|
||||
audioFocusRequest(false) {
|
||||
voicePreviewMediaPlayer!!.pause()
|
||||
voicePreviewObjectAnimator!!.pause()
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopPreviewVoicePlaying() {
|
||||
|
@ -1361,9 +1373,11 @@ class ChatActivity :
|
|||
voicePreviewObjectAnimator!!.end()
|
||||
voicePreviewObjectAnimator = null
|
||||
binding.messageInputView.seekBar.clearAnimation()
|
||||
voicePreviewMediaPlayer!!.stop()
|
||||
voicePreviewMediaPlayer!!.release()
|
||||
voicePreviewMediaPlayer = null
|
||||
audioFocusRequest(false) {
|
||||
voicePreviewMediaPlayer!!.stop()
|
||||
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) {
|
||||
if (!active) {
|
||||
// don't begin to play voice message if screen is not visible anymore.
|
||||
|
@ -1830,8 +1894,9 @@ class ChatActivity :
|
|||
|
||||
mediaPlayer?.let {
|
||||
if (!it.isPlaying) {
|
||||
it.start()
|
||||
Log.d(TAG, "MediaPlayer has Started")
|
||||
audioFocusRequest(true) {
|
||||
it.start()
|
||||
}
|
||||
}
|
||||
|
||||
mediaPlayerHandler = Handler()
|
||||
|
@ -1866,8 +1931,9 @@ class ChatActivity :
|
|||
|
||||
private fun pausePlayback(message: ChatMessage) {
|
||||
if (mediaPlayer!!.isPlaying) {
|
||||
mediaPlayer!!.pause()
|
||||
Log.d(TAG, "MediaPlayer is paused")
|
||||
audioFocusRequest(false) {
|
||||
mediaPlayer!!.pause()
|
||||
}
|
||||
}
|
||||
|
||||
message.isPlayingVoiceMessage = false
|
||||
|
@ -1925,7 +1991,9 @@ class ChatActivity :
|
|||
mediaPlayer?.let {
|
||||
if (it.isPlaying) {
|
||||
Log.d(TAG, "media player is stopped")
|
||||
it.stop()
|
||||
audioFocusRequest(false) {
|
||||
it.stop()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: IllegalStateException) {
|
||||
|
@ -2141,8 +2209,10 @@ class ChatActivity :
|
|||
private fun stopMicInputRecordingAnimation() {
|
||||
if (micInputAudioRecordThread != null) {
|
||||
Log.d(TAG, "Mic Animation Ended")
|
||||
micInputAudioRecorder.stop()
|
||||
micInputAudioRecorder.release()
|
||||
audioFocusRequest(false) {
|
||||
micInputAudioRecorder.stop()
|
||||
micInputAudioRecorder.release()
|
||||
}
|
||||
isMicInputAudioThreadRunning = false
|
||||
micInputAudioRecordThread = null
|
||||
}
|
||||
|
@ -2193,7 +2263,9 @@ class ChatActivity :
|
|||
}
|
||||
|
||||
try {
|
||||
start()
|
||||
audioFocusRequest(true) {
|
||||
start()
|
||||
}
|
||||
mediaRecorderState = MediaRecorderState.RECORDING
|
||||
Log.d(TAG, "recording started")
|
||||
} catch (e: IllegalStateException) {
|
||||
|
@ -2234,8 +2306,10 @@ class ChatActivity :
|
|||
recorder?.apply {
|
||||
try {
|
||||
if (mediaRecorderState == MediaRecorderState.RECORDING) {
|
||||
stop()
|
||||
reset()
|
||||
audioFocusRequest(false) {
|
||||
stop()
|
||||
reset()
|
||||
}
|
||||
mediaRecorderState = MediaRecorderState.INITIAL
|
||||
Log.d(TAG, "stopped recorder")
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ import androidx.core.view.marginBottom
|
|||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.media3.common.AudioAttributes
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
|
@ -165,7 +166,10 @@ class FullScreenMediaActivity : AppCompatActivity() {
|
|||
}
|
||||
|
||||
private fun initializePlayer() {
|
||||
player = ExoPlayer.Builder(applicationContext).build()
|
||||
player = ExoPlayer.Builder(applicationContext)
|
||||
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
||||
.setHandleAudioBecomingNoisy(true)
|
||||
.build()
|
||||
binding.playerView.player = player
|
||||
}
|
||||
|
||||
|
@ -202,6 +206,7 @@ class FullScreenMediaActivity : AppCompatActivity() {
|
|||
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||
supportActionBar?.show()
|
||||
}
|
||||
|
||||
private fun applyWindowInsets() {
|
||||
val playerView = binding.playerView
|
||||
val exoControls = playerView.findViewById<FrameLayout>(R.id.exo_bottom_bar)
|
||||
|
|
Loading…
Reference in a new issue