kunfei 4 лет назад
Родитель
Сommit
0733b664c5

+ 35 - 0
app/src/main/java/io/legado/app/help/TTS.kt

@@ -17,10 +17,14 @@ class TTS {
 
     private val clearTtsRunnable = Runnable { clearTts() }
 
+    private var speakStateListener: SpeakStateListener? = null
+
     private var textToSpeech: TextToSpeech? = null
 
     private var text: String? = null
 
+    private var onInit = false
+
     private val initListener by lazy {
         InitListener()
     }
@@ -29,17 +33,40 @@ class TTS {
         TTSUtteranceListener()
     }
 
+    val isSpeaking: Boolean
+        get() {
+            return textToSpeech?.isSpeaking ?: false
+        }
+
+    @Suppress("unused")
+    fun setSpeakStateListener(speakStateListener: SpeakStateListener) {
+        this.speakStateListener = speakStateListener
+    }
+
+    @Suppress("unused")
+    fun removeSpeakStateListener() {
+        speakStateListener = null
+    }
+
     @Synchronized
     fun speak(text: String) {
         handler.removeCallbacks(clearTtsRunnable)
         this.text = text
+        if (onInit) {
+            return
+        }
         if (textToSpeech == null) {
+            onInit = true
             textToSpeech = TextToSpeech(appCtx, initListener)
         } else {
             addTextToSpeakList()
         }
     }
 
+    fun stop() {
+        textToSpeech?.stop()
+    }
+
     @Synchronized
     fun clearTts() {
         textToSpeech?.let { tts ->
@@ -80,6 +107,7 @@ class TTS {
             } else {
                 appCtx.toastOnUi(R.string.tts_init_failed)
             }
+            onInit = false
         }
 
     }
@@ -92,11 +120,13 @@ class TTS {
         override fun onStart(utteranceId: String?) {
             //开始朗读取消释放资源任务
             handler.removeCallbacks(clearTtsRunnable)
+            speakStateListener?.onStart()
         }
 
         override fun onDone(utteranceId: String?) {
             //一分钟没有朗读释放资源
             handler.postDelayed(clearTtsRunnable, 60000L)
+            speakStateListener?.onDone()
         }
 
         @Deprecated("Deprecated in Java")
@@ -105,4 +135,9 @@ class TTS {
         }
 
     }
+
+    interface SpeakStateListener {
+        fun onStart()
+        fun onDone()
+    }
 }

+ 3 - 4
app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt

@@ -267,16 +267,15 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
 
     @SuppressLint("SetJavaScriptEnabled")
     private fun readAloud() {
-        if (viewModel.textToSpeech?.isSpeaking == true) {
-            viewModel.textToSpeech?.stop()
+        if (viewModel.tts?.isSpeaking == true) {
+            viewModel.tts?.stop()
             upTtsMenu(false)
         } else {
             binding.webView.settings.javaScriptEnabled = true
             binding.webView.evaluateJavascript("document.documentElement.outerHTML") {
                 val html = StringEscapeUtils.unescapeJson(it)
                     .replace("^\"|\"$".toRegex(), "")
-                Jsoup.parse(html).text()
-                viewModel.readAloud(Jsoup.parse(html).textArray())
+                viewModel.readAloud(Jsoup.parse(html).textArray().joinToString("\n"))
             }
         }
     }

+ 17 - 55
app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.kt

@@ -3,20 +3,18 @@ package io.legado.app.ui.rss.read
 import android.app.Application
 import android.content.Intent
 import android.net.Uri
-import android.speech.tts.TextToSpeech
-import android.speech.tts.UtteranceProgressListener
 import android.util.Base64
 import android.webkit.URLUtil
 import androidx.documentfile.provider.DocumentFile
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.viewModelScope
-import io.legado.app.R
 import io.legado.app.base.BaseViewModel
 import io.legado.app.constant.AppConst
 import io.legado.app.data.appDb
 import io.legado.app.data.entities.RssArticle
 import io.legado.app.data.entities.RssSource
 import io.legado.app.data.entities.RssStar
+import io.legado.app.help.TTS
 import io.legado.app.help.http.newCallResponseBody
 import io.legado.app.help.http.okHttpClient
 import io.legado.app.model.analyzeRule.AnalyzeUrl
@@ -27,17 +25,14 @@ import java.io.File
 import java.util.*
 
 
-class ReadRssViewModel(application: Application) : BaseViewModel(application),
-    TextToSpeech.OnInitListener {
+class ReadRssViewModel(application: Application) : BaseViewModel(application) {
     var callBack: CallBack? = null
     var rssSource: RssSource? = null
     var rssArticle: RssArticle? = null
+    var tts: TTS? = null
     val contentLiveData = MutableLiveData<String>()
     val urlLiveData = MutableLiveData<AnalyzeUrl>()
     var rssStar: RssStar? = null
-    var textToSpeech: TextToSpeech? = null
-    private var ttsInitFinish = false
-    private var ttsTextList = arrayListOf<String>()
 
     fun initData(intent: Intent) {
         execute {
@@ -192,59 +187,26 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application),
     }
 
     @Synchronized
-    override fun onInit(status: Int) {
-        if (status == TextToSpeech.SUCCESS) {
-            textToSpeech?.setOnUtteranceProgressListener(TTSUtteranceListener())
-            ttsInitFinish = true
-            play()
-        } else {
-            context.toastOnUi(R.string.tts_init_failed)
-        }
-    }
-
-    @Synchronized
-    private fun play() {
-        if (!ttsInitFinish) return
-        textToSpeech?.stop()
-        ttsTextList.forEach {
-            textToSpeech?.speak(it, TextToSpeech.QUEUE_ADD, null, "rss")
-        }
-    }
+    fun readAloud(text: String) {
+        if (tts == null) {
+            tts = TTS().apply {
+                setSpeakStateListener(object : TTS.SpeakStateListener {
+                    override fun onStart() {
+                        callBack?.upTtsMenu(true)
+                    }
 
-    fun readAloud(textArray: Array<String>) {
-        ttsTextList.clear()
-        ttsTextList.addAll(textArray)
-        textToSpeech?.let {
-            play()
-        } ?: let {
-            textToSpeech = TextToSpeech(context, this)
+                    override fun onDone() {
+                        callBack?.upTtsMenu(false)
+                    }
+                })
+            }
         }
+        tts?.speak(text)
     }
 
     override fun onCleared() {
         super.onCleared()
-        textToSpeech?.stop()
-        textToSpeech?.shutdown()
-    }
-
-    /**
-     * 朗读监听
-     */
-    private inner class TTSUtteranceListener : UtteranceProgressListener() {
-
-        override fun onStart(s: String) {
-            callBack?.upTtsMenu(true)
-        }
-
-        override fun onDone(s: String) {
-            callBack?.upTtsMenu(false)
-        }
-
-        @Deprecated("Deprecated in Java")
-        override fun onError(s: String) {
-
-        }
-
+        tts?.clearTts()
     }
 
     interface CallBack {