From 70d7cc75588c8aa080acf03b5de8bd3acfb4d595 Mon Sep 17 00:00:00 2001 From: litcc Date: Tue, 5 Jan 2021 20:45:17 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=E6=9C=97=E8=AF=BB=E6=97=B6=E7=BF=BB?= =?UTF-8?q?=E9=A1=B5=E9=98=B2=E6=AD=A2=E9=87=8D=E5=A4=8D=E5=8F=91=E9=80=81?= =?UTF-8?q?=E8=AF=B7=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/service/HttpReadAloudService.kt | 127 ++++++++++++++---- 1 file changed, 101 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt b/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt index 2851173ed..e1bb89e61 100644 --- a/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt +++ b/app/src/main/java/io/legado/app/service/HttpReadAloudService.kt @@ -12,11 +12,18 @@ import io.legado.app.service.help.ReadAloud import io.legado.app.service.help.ReadBook import io.legado.app.utils.FileUtils import io.legado.app.utils.LogUtils +import io.legado.app.utils.MD5Utils import io.legado.app.utils.postEvent +import kotlinx.coroutines.delay import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import org.jetbrains.anko.collections.forEachWithIndex import java.io.File import java.io.FileDescriptor import java.io.FileInputStream +import java.net.ConnectException +import java.net.SocketTimeoutException +import java.util.* class HttpReadAloudService : BaseReadAloudService(), MediaPlayer.OnPreparedListener, @@ -55,12 +62,17 @@ class HttpReadAloudService : BaseReadAloudService(), override fun play() { if (contentList.isEmpty()) return - if (nowSpeak == 0) { - downloadAudio() - } else { - val file = getSpeakFile(nowSpeak) - if (file.exists()) { - playAudio(FileInputStream(file).fd) + ReadAloud.httpTTS?.let { + val fileName = md5SpeakFileName(it.url, AppConfig.ttsSpeechRate.toString(), contentList[nowSpeak]) + if (nowSpeak == 0) { + downloadAudio() + } else { + val file = getSpeakFileAsMd5(fileName) + if (file.exists()) { + playAudio(FileInputStream(file).fd) + } else { + downloadAudio() + } } } } @@ -68,28 +80,54 @@ class HttpReadAloudService : BaseReadAloudService(), private fun downloadAudio() { task?.cancel() task = execute { - FileUtils.deleteFile(ttsFolder) - for (index in 0 until contentList.size) { - if (isActive) { - ReadAloud.httpTTS?.let { - AnalyzeUrl( - it.url, - speakText = contentList[index], - speakSpeed = AppConfig.ttsSpeechRate - ).getByteArray().let { bytes -> - if (isActive) { - val file = getSpeakFile(index) - file.writeBytes(bytes) - if (index == nowSpeak) { - @Suppress("BlockingMethodInNonBlockingContext") - val fis = FileInputStream(file) - playAudio(fis.fd) + removeCacheFile() + ReadAloud.httpTTS?.let { + contentList.forEachWithIndex { index, item -> + if (isActive) { + val fileName = + md5SpeakFileName(it.url, AppConfig.ttsSpeechRate.toString(), item) + + if (hasSpeakFile(fileName)) { //已经下载好的语音缓存 + if (index == nowSpeak) { + val file = getSpeakFileAsMd5(fileName) + + @Suppress("BlockingMethodInNonBlockingContext") + val fis = FileInputStream(file) + playAudio(fis.fd) + } + } else if (hasSpeakCacheFile(fileName)) { //缓存文件还在,可能还没下载完 + return@let + } else { //没有下载并且没有缓存文件 + try { + createSpeakCacheFile(fileName) + AnalyzeUrl( + it.url, + speakText = item, + speakSpeed = AppConfig.ttsSpeechRate + ).getByteArray().let { bytes -> + if (isActive) { + val file = getSpeakFileAsMd5(fileName) + //val file = getSpeakFile(index) + file.writeBytes(bytes) + + if (index == nowSpeak) { + @Suppress("BlockingMethodInNonBlockingContext") + val fis = FileInputStream(file) + playAudio(fis.fd) + } + } } + } catch (e: SocketTimeoutException) { + removeSpeakCacheFile(fileName) + // delay(2000) + // downloadAudio() + } catch (e: ConnectException) { + removeSpeakCacheFile(fileName) + } catch (e: Exception) { + removeSpeakCacheFile(fileName) } } } - } else { - break } } } @@ -110,10 +148,47 @@ class HttpReadAloudService : BaseReadAloudService(), } } - private fun getSpeakFile(index: Int = nowSpeak): File { - return FileUtils.createFileIfNotExist("${ttsFolder}${File.separator}${index}.mp3") + private fun speakFilePath() = ttsFolder + File.separator + private fun md5SpeakFileName(url: String, ttsConfig: String, content: String): String { + return MD5Utils.md5Encode16(textChapter!!.title) + "_" + MD5Utils.md5Encode16("$url-|-$ttsConfig-|-$content") + } + + private fun hasSpeakFile(name: String) = + FileUtils.exist("${speakFilePath()}$name.mp3") + + private fun hasSpeakCacheFile(name: String) = + FileUtils.exist("${speakFilePath()}$name.mp3.cache") + + private fun createSpeakCacheFile(name: String): File = + FileUtils.createFileWithReplace("${speakFilePath()}$name.mp3.cache") + + private fun removeSpeakCacheFile(name: String) { + FileUtils.delete("${speakFilePath()}$name.mp3.cache") + } + + private fun getSpeakFileAsMd5(name: String): File = + FileUtils.createFileIfNotExist("${speakFilePath()}$name.mp3") + + private fun removeCacheFile() { + FileUtils.listDirsAndFiles(speakFilePath())?.forEach { + if (it == null) { + return@forEach + } + if (Regex(""".+\.mp3$""").matches(it.name)) { //mp3缓存文件 + val reg = + """^${MD5Utils.md5Encode16(textChapter!!.title)}_[a-z0-9]{16}\.mp3$""".toRegex() + if (!reg.matches(it.name)) { + FileUtils.deleteFile(it.absolutePath) + } + } else { + if (Date().time - it.lastModified() > 30000) { + FileUtils.deleteFile(it.absolutePath) + } + } + } } + override fun pauseReadAloud(pause: Boolean) { super.pauseReadAloud(pause) mediaPlayer.pause() From 8b88b91bb34dbd441d590f90ca347ecb8a7a9d46 Mon Sep 17 00:00:00 2001 From: gedoor Date: Tue, 5 Jan 2021 20:52:25 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/item_bookshelf_list.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/layout/item_bookshelf_list.xml b/app/src/main/res/layout/item_bookshelf_list.xml index f6e0a694d..5a9fefbd2 100644 --- a/app/src/main/res/layout/item_bookshelf_list.xml +++ b/app/src/main/res/layout/item_bookshelf_list.xml @@ -11,8 +11,8 @@ @@ -126,7 +126,7 @@ android:textSize="13sp" app:layout_constraintBottom_toTopOf="@id/tv_last" app:layout_constraintLeft_toRightOf="@+id/iv_read" - app:layout_constraintRight_toLeftOf="@id/fl_has_new" + app:layout_constraintRight_toRightOf="@+id/fl_has_new" app:layout_constraintTop_toBottomOf="@+id/tv_author" /> Date: Tue, 5 Jan 2021 22:40:39 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=8C=89=E5=90=AF=E7=94=A8=E7=A6=81?= =?UTF-8?q?=E7=94=A8=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../book/source/manage/BookSourceActivity.kt | 64 ++++++++++++------- app/src/main/res/menu/book_source.xml | 6 ++ app/src/main/res/values-zh-rHK/strings.xml | 1 + app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 6 files changed, 52 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 0aeceded0..b23e1a641 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -130,6 +130,11 @@ class BookSourceActivity : VMBaseActivity { + item.isChecked = true + sortCheck(Sort.Enable) + initLiveDataBookSource(searchView.query?.toString()) + } R.id.menu_enabled_group -> { searchView.setQuery(getString(R.string.enabled), true) } @@ -187,29 +192,44 @@ class BookSourceActivity : VMBaseActivity { App.db.bookSourceDao.liveDataSearch("%$searchKey%") } - } - bookSourceLiveDate?.observe(this, { data -> - val sourceList = - if (sortAscending) when (sort) { - Sort.Weight -> data.sortedBy { it.weight } - Sort.Name -> data.sortedWith { o1, o2 -> - o1.bookSourceName.cnCompare(o2.bookSourceName) + }.apply { + observe(this@BookSourceActivity, { data -> + val sourceList = + if (sortAscending) when (sort) { + Sort.Weight -> data.sortedBy { it.weight } + Sort.Name -> data.sortedWith { o1, o2 -> + o1.bookSourceName.cnCompare(o2.bookSourceName) + } + Sort.Url -> data.sortedBy { it.bookSourceUrl } + Sort.Update -> data.sortedByDescending { it.lastUpdateTime } + Sort.Enable -> data.sortedWith { o1, o2 -> + var sort = -o1.enabled.compareTo(o2.enabled) + if (sort == 0) { + sort = o1.bookSourceName.cnCompare(o2.bookSourceName) + } + sort + } + else -> data } - Sort.Url -> data.sortedBy { it.bookSourceUrl } - Sort.Update -> data.sortedByDescending { it.lastUpdateTime } - else -> data - } - else when (sort) { - Sort.Weight -> data.sortedByDescending { it.weight } - Sort.Name -> data.sortedWith { o1, o2 -> - o2.bookSourceName.cnCompare(o1.bookSourceName) + else when (sort) { + Sort.Weight -> data.sortedByDescending { it.weight } + Sort.Name -> data.sortedWith { o1, o2 -> + o2.bookSourceName.cnCompare(o1.bookSourceName) + } + Sort.Url -> data.sortedByDescending { it.bookSourceUrl } + Sort.Update -> data.sortedBy { it.lastUpdateTime } + Sort.Enable -> data.sortedWith { o1, o2 -> + var sort = o1.enabled.compareTo(o2.enabled) + if (sort == 0) { + sort = o1.bookSourceName.cnCompare(o2.bookSourceName) + } + sort + } + else -> data.reversed() } - Sort.Url -> data.sortedByDescending { it.bookSourceUrl } - Sort.Update -> data.sortedBy { it.lastUpdateTime } - else -> data.reversed() - } - adapter.setItems(sourceList, adapter.diffItemCallback) - }) + adapter.setItems(sourceList, adapter.diffItemCallback) + }) + } } private fun showHelp() { @@ -483,6 +503,6 @@ class BookSourceActivity : VMBaseActivity + + + diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 63f2ec2e1..3192e781d 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -799,5 +799,6 @@ 导入书单 预下载 预先下载10章正文 + 启用排序 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index af90b7f86..1b64a2d78 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -800,5 +800,6 @@ 导入书单 预下载 预先下载10章正文 + 启用排序 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 48eb53cb6..ad6bfbce7 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -803,5 +803,6 @@ 导入书单 预下载 预先下载10章正文 + 启用排序 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2c078fec..c38246704 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -806,5 +806,6 @@ 导入书单 预下载 预先下载10章正文 + 启用排序