Merge pull request #3427 from kiwix/Issue#3408

Fixes of Text to Speech init failed
This commit is contained in:
Kelson 2023-06-20 08:37:45 +02:00 committed by GitHub
commit c29f40e128
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 14 deletions

View File

@ -18,6 +18,13 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<queries>
<intent>
<action android:name="android.intent.action.TTS_SERVICE" />
</intent>
</queries>
<application <application
android:allowBackup="true" android:allowBackup="true"
android:fullBackupContent="@xml/backup_rules" android:fullBackupContent="@xml/backup_rules"

View File

@ -326,6 +326,7 @@ abstract class CoreReaderFragment :
private lateinit var serviceConnection: ServiceConnection private lateinit var serviceConnection: ServiceConnection
private var readAloudService: ReadAloudService? = null private var readAloudService: ReadAloudService? = null
private var navigationHistoryList: MutableList<NavigationHistoryListItem> = ArrayList() private var navigationHistoryList: MutableList<NavigationHistoryListItem> = ArrayList()
private var isReadSelection = false
private var storagePermissionForNotesLauncher: ActivityResultLauncher<String>? = private var storagePermissionForNotesLauncher: ActivityResultLauncher<String>? =
registerForActivityResult( registerForActivityResult(
@ -366,7 +367,12 @@ abstract class CoreReaderFragment :
protected open fun configureWebViewSelectionHandler(menu: Menu?) { protected open fun configureWebViewSelectionHandler(menu: Menu?) {
menu?.findItem(R.id.menu_speak_text)?.setOnMenuItemClickListener { menu?.findItem(R.id.menu_speak_text)?.setOnMenuItemClickListener {
getCurrentWebView()?.let { currentWebView -> tts?.readSelection(currentWebView) } if (tts?.isInitialized == false) {
isReadSelection = true
tts?.initializeTTS()
} else {
startReadSelection()
}
actionMode?.finish() actionMode?.finish()
true true
} }
@ -853,7 +859,11 @@ abstract class CoreReaderFragment :
requireActivity(), requireActivity(),
object : OnInitSucceedListener { object : OnInitSucceedListener {
override fun onInitSucceed() { override fun onInitSucceed() {
// do nothing it's default override method if (isReadSelection) {
startReadSelection()
} else {
startReadAloud()
}
} }
}, },
object : OnSpeakingListener { object : OnSpeakingListener {
@ -900,6 +910,18 @@ abstract class CoreReaderFragment :
} }
} }
private fun startReadAloud() {
getCurrentWebView()?.let {
tts?.readAloud(it)
}
}
private fun startReadSelection() {
getCurrentWebView()?.let {
tts?.readSelection(it)
}
}
@OnClick(R2.id.activity_main_button_pause_tts) @OnClick(R2.id.activity_main_button_pause_tts)
fun pauseTts() { fun pauseTts() {
if (tts?.currentTTSTask == null) { if (tts?.currentTTSTask == null) {
@ -1130,7 +1152,12 @@ abstract class CoreReaderFragment :
if (isBackToTopEnabled) { if (isBackToTopEnabled) {
backToTopButton?.hide() backToTopButton?.hide()
} }
getCurrentWebView()?.let { tts?.readAloud(it) } if (tts?.isInitialized == false) {
isReadSelection = false
tts?.initializeTTS()
} else {
startReadAloud()
}
} }
View.VISIBLE -> { View.VISIBLE -> {
if (isBackToTopEnabled) { if (isBackToTopEnabled) {

View File

@ -28,7 +28,6 @@ import android.speech.tts.TextToSpeech
import android.speech.tts.TextToSpeech.Engine import android.speech.tts.TextToSpeech.Engine
import android.speech.tts.TextToSpeech.LANG_MISSING_DATA import android.speech.tts.TextToSpeech.LANG_MISSING_DATA
import android.speech.tts.TextToSpeech.LANG_NOT_SUPPORTED 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.QUEUE_ADD
import android.speech.tts.TextToSpeech.SUCCESS import android.speech.tts.TextToSpeech.SUCCESS
import android.speech.tts.UtteranceProgressListener import android.speech.tts.UtteranceProgressListener
@ -36,7 +35,6 @@ import android.util.Log
import android.webkit.JavascriptInterface import android.webkit.JavascriptInterface
import android.webkit.WebView import android.webkit.WebView
import android.widget.Toast import android.widget.Toast
import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.extensions.toast
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
@ -54,7 +52,7 @@ import java.util.concurrent.atomic.AtomicInteger
*/ */
class KiwixTextToSpeech internal constructor( class KiwixTextToSpeech internal constructor(
val context: Context, val context: Context,
onInitSucceedListener: OnInitSucceedListener, private val onInitSucceedListener: OnInitSucceedListener,
val onSpeakingListener: OnSpeakingListener, val onSpeakingListener: OnSpeakingListener,
private var onAudioFocusChangeListener: OnAudioFocusChangeListener? = null, private var onAudioFocusChangeListener: OnAudioFocusChangeListener? = null,
private val zimReaderContainer: ZimReaderContainer private val zimReaderContainer: ZimReaderContainer
@ -63,26 +61,35 @@ class KiwixTextToSpeech internal constructor(
private val focusLock: Any = Any() private val focusLock: Any = Any()
private val am: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager private val am: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
@JvmField var currentTTSTask: TTSTask? = null @JvmField var currentTTSTask: TTSTask? = null
private val tts: TextToSpeech = TextToSpeech( private lateinit var tts: TextToSpeech
instance,
OnInitListener { status: Int -> /**
if (status == SUCCESS) { * Initializes the TextToSpeech object.
*/
fun initializeTTS() {
tts = TextToSpeech(
context
) { status: Int ->
if (status == TextToSpeech.SUCCESS) {
Log.d(TAG_KIWIX, "TextToSpeech was initialized successfully.") Log.d(TAG_KIWIX, "TextToSpeech was initialized successfully.")
this.isInitialized = true this.isInitialized = true
onInitSucceedListener.onInitSucceed() onInitSucceedListener.onInitSucceed()
} else { } else {
Log.e(TAG_KIWIX, "Initialization of TextToSpeech Failed!") Log.e(TAG_KIWIX, "Initialization of TextToSpeech Failed!")
context.toast(R.string.texttospeech_initialization_failed, Toast.LENGTH_SHORT) context.toast(
R.string.texttospeech_initialization_failed,
Toast.LENGTH_SHORT
)
} }
} }
) }
/** /**
* Returns whether the TTS is initialized. * Returns whether the TTS is initialized.
* *
* @return `true` if TTS is initialized; `false` otherwise * @return `true` if TTS is initialized; `false` otherwise
*/ */
private var isInitialized = false var isInitialized = false
init { init {
Log.d(TAG_KIWIX, "Initializing TextToSpeech") Log.d(TAG_KIWIX, "Initializing TextToSpeech")
@ -214,7 +221,9 @@ class KiwixTextToSpeech internal constructor(
* {@link https://developer.android.com/guide/topics/media-apps/audio-focus#audio-focus-change } * {@link https://developer.android.com/guide/topics/media-apps/audio-focus#audio-focus-change }
*/ */
fun shutdown() { fun shutdown() {
tts.shutdown() if (::tts.isInitialized) {
tts.shutdown()
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
focusRequest?.let(am::abandonAudioFocusRequest) focusRequest?.let(am::abandonAudioFocusRequest)
focusRequest = null focusRequest = null