pull/2343/head
kunfei 2 years ago
parent f424a18b5b
commit 9706195ae2
  1. 35
      app/src/main/java/io/legado/app/help/TTS.kt
  2. 7
      app/src/main/java/io/legado/app/ui/rss/read/ReadRssActivity.kt
  3. 72
      app/src/main/java/io/legado/app/ui/rss/read/ReadRssViewModel.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()
}
}

@ -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"))
}
}
}

@ -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 {

Loading…
Cancel
Save