This commit is contained in:
kunfei 2023-08-01 08:31:17 +08:00
parent d639e4957b
commit bbea812c6d
2 changed files with 58 additions and 53 deletions

View File

@ -52,9 +52,9 @@ import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.ag2s.epublib.domain.Author import me.ag2s.epublib.domain.Author
import me.ag2s.epublib.domain.Date import me.ag2s.epublib.domain.Date
import me.ag2s.epublib.domain.EpubBook import me.ag2s.epublib.domain.EpubBook
@ -73,6 +73,7 @@ import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.nio.charset.Charset import java.nio.charset.Charset
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlin.coroutines.coroutineContext
/** /**
* 导出书籍服务 * 导出书籍服务
@ -283,7 +284,7 @@ class ExportBookService : BaseService() {
private suspend fun getAllContents( private suspend fun getAllContents(
book: Book, book: Book,
append: (text: String, srcList: ArrayList<SrcData>?) -> Unit append: (text: String, srcList: ArrayList<SrcData>?) -> Unit
) = withContext(IO) { ) {
val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule() val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule()
val contentProcessor = ContentProcessor.get(book.name, book.origin) val contentProcessor = ContentProcessor.get(book.name, book.origin)
val qy = "${book.name}\n${ val qy = "${book.name}\n${
@ -308,7 +309,7 @@ class ExportBookService : BaseService() {
} }
} else { } else {
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter -> appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter ->
ensureActive() coroutineContext.ensureActive()
postEvent(EventBus.EXPORT_BOOK, book.bookUrl) postEvent(EventBus.EXPORT_BOOK, book.bookUrl)
exportProgress[book.bookUrl] = index exportProgress[book.bookUrl] = index
val result = getExportData(book, chapter, contentProcessor, useReplace) val result = getExportData(book, chapter, contentProcessor, useReplace)
@ -364,6 +365,7 @@ class ExportBookService : BaseService() {
* @since 2023/5/22 * @since 2023/5/22
* @author Discut * @author Discut
*/ */
@SuppressLint("ObsoleteSdkInt")
private fun paresScope(scope: String): IntArray { private fun paresScope(scope: String): IntArray {
val split = scope.split(",") val split = scope.split(",")
@ -606,12 +608,12 @@ class ExportBookService : BaseService() {
contentModel: String, contentModel: String,
book: Book, book: Book,
epubBook: EpubBook epubBook: EpubBook
) = withContext(IO) { ) {
//正文 //正文
val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule() val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule()
val contentProcessor = ContentProcessor.get(book.name, book.origin) val contentProcessor = ContentProcessor.get(book.name, book.origin)
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter -> appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter ->
ensureActive() coroutineContext.ensureActive()
postEvent(EventBus.EXPORT_BOOK, book.bookUrl) postEvent(EventBus.EXPORT_BOOK, book.bookUrl)
exportProgress[book.bookUrl] = index exportProgress[book.bookUrl] = index
BookHelp.getContent(book, chapter).let { content -> BookHelp.getContent(book, chapter).let { content ->
@ -713,7 +715,7 @@ class ExportBookService : BaseService() {
suspend fun export( suspend fun export(
path: String, path: String,
book: Book book: Book
) = withContext(IO) { ) {
exportProgress[book.bookUrl] = 0 exportProgress[book.bookUrl] = 0
exportMsg.remove(book.bookUrl) exportMsg.remove(book.bookUrl)
postEvent(EventBus.EXPORT_BOOK, book.bookUrl) postEvent(EventBus.EXPORT_BOOK, book.bookUrl)
@ -728,27 +730,29 @@ class ExportBookService : BaseService() {
var progressBar = 0.0 var progressBar = 0.0
epubList.forEachIndexed { index, ep -> epubList.forEachIndexed { index, ep ->
val (filename, epubBook) = ep val (filename, epubBook) = ep
val asyncBlock = async { coroutineScope {
//设置正文 val asyncBlock = async {
setEpubContent( //设置正文
contentModel, setEpubContent(
book, contentModel,
epubBook, book,
index epubBook,
) { _, _ -> index
// 将章节写入内存时更新进度条 ) { _, _ ->
postEvent(EventBus.EXPORT_BOOK, book.bookUrl) // 将章节写入内存时更新进度条
progressBar += book.totalChapterNum.toDouble() / scope.size / 2 postEvent(EventBus.EXPORT_BOOK, book.bookUrl)
exportProgress[book.bookUrl] = progressBar.toInt() progressBar += book.totalChapterNum.toDouble() / scope.size / 2
} exportProgress[book.bookUrl] = progressBar.toInt()
save2Drive(filename, epubBook, doc) { total, _ -> }
//写入硬盘时更新进度条 save2Drive(filename, epubBook, doc) { total, _ ->
progressBar += book.totalChapterNum.toDouble() / epubList.size / total / 2 //写入硬盘时更新进度条
postEvent(EventBus.EXPORT_BOOK, book.bookUrl) progressBar += book.totalChapterNum.toDouble() / epubList.size / total / 2
exportProgress[book.bookUrl] = progressBar.toInt() postEvent(EventBus.EXPORT_BOOK, book.bookUrl)
exportProgress[book.bookUrl] = progressBar.toInt()
}
} }
asyncBlocks.add(asyncBlock)
} }
asyncBlocks.add(asyncBlock)
} }
asyncBlocks.forEach { it.await() } asyncBlocks.forEach { it.await() }
} }
@ -760,27 +764,29 @@ class ExportBookService : BaseService() {
var progressBar = 0.0 var progressBar = 0.0
epubList.forEachIndexed { index, ep -> epubList.forEachIndexed { index, ep ->
val (filename, epubBook) = ep val (filename, epubBook) = ep
val asyncBlock = async { coroutineScope {
//设置正文 val asyncBlock = async {
setEpubContent( //设置正文
contentModel, setEpubContent(
book, contentModel,
epubBook, book,
index epubBook,
) { _, _ -> index
postEvent(EventBus.EXPORT_BOOK, book.bookUrl) ) { _, _ ->
exportProgress[book.bookUrl] = postEvent(EventBus.EXPORT_BOOK, book.bookUrl)
exportProgress[book.bookUrl]?.plus(book.totalChapterNum / scope.size) exportProgress[book.bookUrl] =
?: 1 exportProgress[book.bookUrl]?.plus(book.totalChapterNum / scope.size)
} ?: 1
save2Drive(filename, epubBook, file) { total, _ -> }
//设置进度 save2Drive(filename, epubBook, file) { total, _ ->
progressBar += book.totalChapterNum.toDouble() / epubList.size / total / 2 //设置进度
postEvent(EventBus.EXPORT_BOOK, book.bookUrl) progressBar += book.totalChapterNum.toDouble() / epubList.size / total / 2
exportProgress[book.bookUrl] = progressBar.toInt() postEvent(EventBus.EXPORT_BOOK, book.bookUrl)
exportProgress[book.bookUrl] = progressBar.toInt()
}
} }
asyncBlocks.add(asyncBlock)
} }
asyncBlocks.add(asyncBlock)
} }
asyncBlocks.forEach { it.await() } asyncBlocks.forEach { it.await() }
} }
@ -803,7 +809,7 @@ class ExportBookService : BaseService() {
epubBook: EpubBook, epubBook: EpubBook,
epubBookIndex: Int, epubBookIndex: Int,
updateProgress: (chapterList: MutableList<BookChapter>, index: Int) -> Unit updateProgress: (chapterList: MutableList<BookChapter>, index: Int) -> Unit
) = withContext(IO) { ) {
//正文 //正文
val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule() val useReplace = AppConfig.exportUseReplace && book.getUseReplaceRule()
val contentProcessor = ContentProcessor.get(book.name, book.origin) val contentProcessor = ContentProcessor.get(book.name, book.origin)
@ -825,7 +831,7 @@ class ExportBookService : BaseService() {
if ((epubBookIndex + 1) * size > scope.size) scope.size else (epubBookIndex + 1) * size if ((epubBookIndex + 1) * size > scope.size) scope.size else (epubBookIndex + 1) * size
) )
chapterList.forEachIndexed { index, chapter -> chapterList.forEachIndexed { index, chapter ->
ensureActive() coroutineContext.ensureActive()
updateProgress(chapterList, index) updateProgress(chapterList, index)
BookHelp.getContent(book, chapter).let { content -> BookHelp.getContent(book, chapter).let { content ->
var content1 = fixPic( var content1 = fixPic(

View File

@ -27,7 +27,6 @@ import io.legado.app.utils.printOnDebug
import io.legado.app.utils.servicePendingIntent import io.legado.app.utils.servicePendingIntent
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -35,13 +34,13 @@ import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import okhttp3.Response import okhttp3.Response
import org.mozilla.javascript.WrappedException import org.mozilla.javascript.WrappedException
import java.io.File import java.io.File
import java.io.InputStream import java.io.InputStream
import java.net.ConnectException import java.net.ConnectException
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
import kotlin.coroutines.coroutineContext
/** /**
* 在线朗读 * 在线朗读
@ -157,7 +156,7 @@ class HttpReadAloudService : BaseReadAloudService(),
private suspend fun getSpeakStream( private suspend fun getSpeakStream(
httpTts: HttpTTS, httpTts: HttpTTS,
speakText: String speakText: String
): InputStream? = withContext(IO) { ): InputStream? {
while (true) { while (true) {
try { try {
val analyzeUrl = AnalyzeUrl( val analyzeUrl = AnalyzeUrl(
@ -168,7 +167,7 @@ class HttpReadAloudService : BaseReadAloudService(),
headerMapF = httpTts.getHeaderMap(true) headerMapF = httpTts.getHeaderMap(true)
) )
var response = analyzeUrl.getResponseAwait() var response = analyzeUrl.getResponseAwait()
ensureActive() coroutineContext.ensureActive()
val checkJs = httpTts.loginCheckJs val checkJs = httpTts.loginCheckJs
if (checkJs?.isNotBlank() == true) { if (checkJs?.isNotBlank() == true) {
response = analyzeUrl.evalJS(checkJs, response) as Response response = analyzeUrl.evalJS(checkJs, response) as Response
@ -183,10 +182,10 @@ class HttpReadAloudService : BaseReadAloudService(),
} }
} }
} }
ensureActive() coroutineContext.ensureActive()
response.body!!.byteStream().let { stream -> response.body!!.byteStream().let { stream ->
downloadErrorNo = 0 downloadErrorNo = 0
return@withContext stream return stream
} }
} catch (e: Exception) { } catch (e: Exception) {
when (e) { when (e) {
@ -227,7 +226,7 @@ class HttpReadAloudService : BaseReadAloudService(),
} }
} }
} }
return@withContext null return null
} }
private fun md5SpeakFileName(content: String): String { private fun md5SpeakFileName(content: String): String {