diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/KiwixTextToSpeech.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/KiwixTextToSpeech.kt index 3a4608809..e39bc6b76 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/KiwixTextToSpeech.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/KiwixTextToSpeech.kt @@ -18,14 +18,16 @@ package org.kiwix.kiwixmobile.core.main import android.content.Context +import android.media.AudioAttributes +import android.media.AudioFocusRequest import android.media.AudioManager import android.media.AudioManager.OnAudioFocusChangeListener +import android.os.Build import android.speech.tts.TextToSpeech import android.speech.tts.TextToSpeech.Engine import android.speech.tts.TextToSpeech.LANG_MISSING_DATA import android.speech.tts.TextToSpeech.LANG_NOT_SUPPORTED import android.speech.tts.TextToSpeech.OnInitListener -import android.speech.tts.TextToSpeech.QUEUE_ADD import android.speech.tts.TextToSpeech.SUCCESS import android.speech.tts.UtteranceProgressListener import android.util.Log @@ -55,6 +57,7 @@ class KiwixTextToSpeech internal constructor( private var onAudioFocusChangeListener: OnAudioFocusChangeListener? = null, private val zimReaderContainer: ZimReaderContainer ) { + private var focusRequest: AudioFocusRequest? = null private val focusLock: Any = Any() private val am: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager @JvmField var currentTTSTask: TTSTask? = null @@ -157,6 +160,19 @@ class KiwixTextToSpeech internal constructor( } private fun requestAudioFocus(): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + focusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) + .setAudioAttributes(AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build()) + .setAcceptsDelayedFocusGain(true) + .setOnAudioFocusChangeListener(onAudioFocusChangeListener!!) + .setWillPauseWhenDucked(true) + .build() + + val focusGain = am.requestAudioFocus(focusRequest!!) + synchronized(focusLock) { + return@requestAudioFocus focusGain == AudioManager.AUDIOFOCUS_REQUEST_GRANTED + } + } val audioFocusRequest = am.requestAudioFocus( onAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN @@ -190,7 +206,11 @@ class KiwixTextToSpeech internal constructor( */ fun shutdown() { tts.shutdown() - am.abandonAudioFocus(onAudioFocusChangeListener) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + focusRequest?.let(am::abandonAudioFocusRequest) + } else { + am.abandonAudioFocus(onAudioFocusChangeListener) + } } /** @@ -231,11 +251,12 @@ class KiwixTextToSpeech internal constructor( paused = false // The utterance ID isn't actually used anywhere, the param is passed only to force // the utterance listener to be notified - val params = hashMapOf(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID to "kiwixLastMessage") if (currentPiece.get() < pieces.size) { tts.speak( - pieces[currentPiece.getAndIncrement()], QUEUE_ADD, - params + pieces[currentPiece.getAndIncrement()], + TextToSpeech.QUEUE_ADD, + null, + "kiwixLastMessage" ) } else { stop() @@ -250,7 +271,12 @@ class KiwixTextToSpeech internal constructor( if (line >= pieces.size && !paused) { stop() } else { - tts.speak(pieces[line], QUEUE_ADD, params) + tts.speak( + pieces[currentPiece.getAndIncrement()], + TextToSpeech.QUEUE_ADD, + null, + "kiwixLastMessage" + ) currentPiece.getAndIncrement() } }