This commit is contained in:
Horis 2024-01-27 20:25:23 +08:00
parent c9d07d08c4
commit 3882904f1d
13 changed files with 176 additions and 151 deletions

View File

@ -31,7 +31,12 @@ abstract class BaseService : LifecycleService() {
super.onCreate() super.onCreate()
LifecycleHelp.onServiceCreate(this) LifecycleHelp.onServiceCreate(this)
checkNotificationPermission() checkNotificationPermission()
upNotification() }
@CallSuper
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startForegroundNotification()
return super.onStartCommand(intent, flags, startId)
} }
@CallSuper @CallSuper
@ -52,9 +57,9 @@ abstract class BaseService : LifecycleService() {
} }
/** /**
* 更新通知 * 开启前台服务并发送通知
*/ */
open fun upNotification() { open fun startForegroundNotification() {
} }
@ -67,7 +72,7 @@ abstract class BaseService : LifecycleService() {
.rationale(R.string.notification_permission_rationale) .rationale(R.string.notification_permission_rationale)
.onGranted { .onGranted {
if (lifecycleScope.isActive) { if (lifecycleScope.isActive) {
upNotification() startForegroundNotification()
} }
} }
.request() .request()

View File

@ -14,7 +14,13 @@ import io.legado.app.help.RuleBigDataHelp
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.model.analyzeRule.RuleDataInterface import io.legado.app.model.analyzeRule.RuleDataInterface
import io.legado.app.utils.* import io.legado.app.utils.ChineseUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.fromJsonObject
import io.legado.app.utils.replace
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -110,7 +116,7 @@ data class BookChapter(
try { try {
val mDisplayTitle = if (item.isRegex) { val mDisplayTitle = if (item.isRegex) {
displayTitle.replace( displayTitle.replace(
item.pattern.toRegex(), item.regex,
item.replacement, item.replacement,
item.getValidTimeoutMillisecond() item.getValidTimeoutMillisecond()
) )

View File

@ -4,11 +4,13 @@ import android.os.Parcelable
import android.text.TextUtils import android.text.TextUtils
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.Index import androidx.room.Index
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.AppLog import io.legado.app.constant.AppLog
import io.legado.app.exception.NoStackTraceException import io.legado.app.exception.NoStackTraceException
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import splitties.init.appCtx import splitties.init.appCtx
import java.util.regex.Pattern import java.util.regex.Pattern
@ -68,6 +70,12 @@ data class ReplaceRule(
return id.hashCode() return id.hashCode()
} }
@delegate:Ignore
@IgnoredOnParcel
val regex: Regex by lazy {
pattern.toRegex()
}
fun getDisplayNameGroup(): String { fun getDisplayNameGroup(): String {
return if (group.isNullOrBlank()) { return if (group.isNullOrBlank()) {
name name

View File

@ -152,7 +152,7 @@ class ContentProcessor private constructor(
try { try {
val tmp = if (item.isRegex) { val tmp = if (item.isRegex) {
mContent.replace( mContent.replace(
item.pattern.toRegex(), item.regex,
item.replacement, item.replacement,
item.getValidTimeoutMillisecond() item.getValidTimeoutMillisecond()
) )

View File

@ -1,48 +0,0 @@
package io.legado.app.help.coroutine
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.PriorityBlockingQueue
import java.util.concurrent.atomic.AtomicInteger
class OrderCoroutine<T>(val threadCount: Int) {
private val taskList = ArrayList<suspend CoroutineScope.() -> T>()
private val taskResultMap = ConcurrentHashMap<Int, T>()
private val finishTaskIndex = PriorityBlockingQueue<Int>()
private suspend fun start() = coroutineScope {
val taskIndex = AtomicInteger(0)
val tasks = taskList.toList()
for (i in 1..threadCount) {
launch {
while (true) {
ensureActive()
val curIndex = taskIndex.getAndIncrement()
val task = tasks.getOrNull(curIndex) ?: return@launch
taskResultMap[curIndex] = task.invoke(this)
finishTaskIndex.add(curIndex)
}
}
}
}
fun submit(block: suspend CoroutineScope.() -> T) {
taskList.add(block)
}
suspend fun collect(block: (index: Int, result: T) -> Unit) = withContext(IO) {
var index = 0
val taskSize = taskList.size
launch { start() }
while (index < taskSize) {
ensureActive()
if (finishTaskIndex.peek() == index) {
finishTaskIndex.poll()
block.invoke(index, taskResultMap.remove(index)!!)
index++
}
}
}
}

View File

@ -83,6 +83,17 @@ object CacheBook {
} }
} }
fun clear() {
successDownloadSet.clear()
errorDownloadMap.clear()
}
fun close() {
cacheBookMap.forEach { it.value.stop() }
cacheBookMap.clear()
clear()
}
val downloadSummary: String val downloadSummary: String
get() { get() {
return "正在下载:${onDownloadCount}|等待中:${waitCount}|失败:${errorDownloadMap.count()}|成功:${successDownloadSet.size}" return "正在下载:${onDownloadCount}|等待中:${waitCount}|失败:${errorDownloadMap.count()}|成功:${successDownloadSet.size}"

View File

@ -55,6 +55,7 @@ import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import splitties.init.appCtx import splitties.init.appCtx
import splitties.systemservices.audioManager import splitties.systemservices.audioManager
import splitties.systemservices.notificationManager
import splitties.systemservices.powerManager import splitties.systemservices.powerManager
import splitties.systemservices.wifiManager import splitties.systemservices.wifiManager
@ -135,7 +136,7 @@ class AudioPlayService : BaseService(),
.get() .get()
}.onSuccess { }.onSuccess {
cover = it cover = it
upNotification() upAudioPlayNotification()
} }
} }
@ -191,7 +192,7 @@ class AudioPlayService : BaseService(),
wakeLock.acquire() wakeLock.acquire()
wifiLock?.acquire() wifiLock?.acquire()
} }
upNotification() upAudioPlayNotification()
if (!requestFocus()) { if (!requestFocus()) {
return return
} }
@ -235,7 +236,7 @@ class AudioPlayService : BaseService(),
upMediaSessionPlaybackState(PlaybackStateCompat.STATE_PAUSED) upMediaSessionPlaybackState(PlaybackStateCompat.STATE_PAUSED)
AudioPlay.status = Status.PAUSE AudioPlay.status = Status.PAUSE
postEvent(EventBus.AUDIO_STATE, Status.PAUSE) postEvent(EventBus.AUDIO_STATE, Status.PAUSE)
upNotification() upAudioPlayNotification()
} catch (e: Exception) { } catch (e: Exception) {
e.printOnDebug() e.printOnDebug()
} }
@ -263,7 +264,7 @@ class AudioPlayService : BaseService(),
upMediaSessionPlaybackState(PlaybackStateCompat.STATE_PLAYING) upMediaSessionPlaybackState(PlaybackStateCompat.STATE_PLAYING)
AudioPlay.status = Status.PLAY AudioPlay.status = Status.PLAY
postEvent(EventBus.AUDIO_STATE, Status.PLAY) postEvent(EventBus.AUDIO_STATE, Status.PLAY)
upNotification() upAudioPlayNotification()
} catch (e: Exception) { } catch (e: Exception) {
e.printOnDebug() e.printOnDebug()
stopSelf() stopSelf()
@ -335,7 +336,7 @@ class AudioPlayService : BaseService(),
AudioPlay.next(this) AudioPlay.next(this)
} }
} }
upNotification() upAudioPlayNotification()
} }
/** /**
@ -370,7 +371,7 @@ class AudioPlayService : BaseService(),
*/ */
private fun doDs() { private fun doDs() {
postEvent(EventBus.AUDIO_DS, timeMinute) postEvent(EventBus.AUDIO_DS, timeMinute)
upNotification() upAudioPlayNotification()
dsJob?.cancel() dsJob?.cancel()
dsJob = lifecycleScope.launch { dsJob = lifecycleScope.launch {
while (isActive) { while (isActive) {
@ -384,7 +385,7 @@ class AudioPlayService : BaseService(),
} }
} }
postEvent(EventBus.AUDIO_DS, timeMinute) postEvent(EventBus.AUDIO_DS, timeMinute)
upNotification() upAudioPlayNotification()
} }
} }
} }
@ -583,67 +584,78 @@ class AudioPlayService : BaseService(),
} }
} }
private fun createNotification(): NotificationCompat.Builder {
var nTitle: String = when {
pause -> getString(R.string.audio_pause)
timeMinute in 1..60 -> getString(
R.string.playing_timer,
timeMinute
)
else -> getString(R.string.audio_play_t)
}
nTitle += ": ${AudioPlay.book?.name}"
var nSubtitle = AudioPlay.durChapter?.title
if (nSubtitle.isNullOrEmpty()) {
nSubtitle = getString(R.string.audio_play_s)
}
val builder = NotificationCompat
.Builder(this@AudioPlayService, AppConst.channelIdReadAloud)
.setSmallIcon(R.drawable.ic_volume_up)
.setSubText(getString(R.string.audio))
.setOngoing(true)
.setContentTitle(nTitle)
.setContentText(nSubtitle)
.setContentIntent(
activityPendingIntent<AudioPlayActivity>("activity")
)
builder.setLargeIcon(cover)
if (pause) {
builder.addAction(
R.drawable.ic_play_24dp,
getString(R.string.resume),
servicePendingIntent<AudioPlayService>(IntentAction.resume)
)
} else {
builder.addAction(
R.drawable.ic_pause_24dp,
getString(R.string.pause),
servicePendingIntent<AudioPlayService>(IntentAction.pause)
)
}
builder.addAction(
R.drawable.ic_stop_black_24dp,
getString(R.string.stop),
servicePendingIntent<AudioPlayService>(IntentAction.stop)
)
builder.addAction(
R.drawable.ic_time_add_24dp,
getString(R.string.set_timer),
servicePendingIntent<AudioPlayService>(IntentAction.addTimer)
)
builder.setStyle(
androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mediaSessionCompat?.sessionToken)
)
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
return builder
}
private fun upAudioPlayNotification() {
execute {
createNotification()
}.onSuccess {
notificationManager.notify(NotificationId.AudioPlayService, it.build())
}
}
/** /**
* 更新通知 * 更新通知
*/ */
override fun upNotification() { override fun startForegroundNotification() {
execute { execute {
var nTitle: String = when { createNotification()
pause -> getString(R.string.audio_pause)
timeMinute in 1..60 -> getString(
R.string.playing_timer,
timeMinute
)
else -> getString(R.string.audio_play_t)
}
nTitle += ": ${AudioPlay.book?.name}"
var nSubtitle = AudioPlay.durChapter?.title
if (nSubtitle.isNullOrEmpty()) {
nSubtitle = getString(R.string.audio_play_s)
}
val builder = NotificationCompat
.Builder(this@AudioPlayService, AppConst.channelIdReadAloud)
.setSmallIcon(R.drawable.ic_volume_up)
.setSubText(getString(R.string.audio))
.setOngoing(true)
.setContentTitle(nTitle)
.setContentText(nSubtitle)
.setContentIntent(
activityPendingIntent<AudioPlayActivity>("activity")
)
builder.setLargeIcon(cover)
if (pause) {
builder.addAction(
R.drawable.ic_play_24dp,
getString(R.string.resume),
servicePendingIntent<AudioPlayService>(IntentAction.resume)
)
} else {
builder.addAction(
R.drawable.ic_pause_24dp,
getString(R.string.pause),
servicePendingIntent<AudioPlayService>(IntentAction.pause)
)
}
builder.addAction(
R.drawable.ic_stop_black_24dp,
getString(R.string.stop),
servicePendingIntent<AudioPlayService>(IntentAction.stop)
)
builder.addAction(
R.drawable.ic_time_add_24dp,
getString(R.string.set_timer),
servicePendingIntent<AudioPlayService>(IntentAction.addTimer)
)
builder.setStyle(
androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mediaSessionCompat?.sessionToken)
)
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
builder
}.onSuccess { }.onSuccess {
startForeground(NotificationId.AudioPlayService, it.build()) startForeground(NotificationId.AudioPlayService, it.build())
} }

View File

@ -21,7 +21,13 @@ import androidx.media.AudioFocusRequestCompat
import androidx.media.AudioManagerCompat import androidx.media.AudioManagerCompat
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseService import io.legado.app.base.BaseService
import io.legado.app.constant.* import io.legado.app.constant.AppConst
import io.legado.app.constant.AppLog
import io.legado.app.constant.EventBus
import io.legado.app.constant.IntentAction
import io.legado.app.constant.NotificationId
import io.legado.app.constant.PreferKey
import io.legado.app.constant.Status
import io.legado.app.help.MediaHelp import io.legado.app.help.MediaHelp
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.help.glide.ImageLoader import io.legado.app.help.glide.ImageLoader
@ -30,10 +36,18 @@ import io.legado.app.model.ReadBook
import io.legado.app.receiver.MediaButtonReceiver import io.legado.app.receiver.MediaButtonReceiver
import io.legado.app.ui.book.read.ReadBookActivity import io.legado.app.ui.book.read.ReadBookActivity
import io.legado.app.ui.book.read.page.entities.TextChapter import io.legado.app.ui.book.read.page.entities.TextChapter
import io.legado.app.utils.* import io.legado.app.utils.activityPendingIntent
import kotlinx.coroutines.* import io.legado.app.utils.broadcastPendingIntent
import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.observeEvent
import io.legado.app.utils.postEvent
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import splitties.init.appCtx import splitties.init.appCtx
import splitties.systemservices.audioManager import splitties.systemservices.audioManager
import splitties.systemservices.notificationManager import splitties.systemservices.notificationManager
@ -158,7 +172,6 @@ abstract class BaseReadAloudService : BaseService(),
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
upNotification()
when (intent?.action) { when (intent?.action) {
IntentAction.play -> newReadAloud( IntentAction.play -> newReadAloud(
intent.getBooleanExtra("play", true), intent.getBooleanExtra("play", true),
@ -516,7 +529,7 @@ abstract class BaseReadAloudService : BaseService(),
/** /**
* 更新通知 * 更新通知
*/ */
override fun upNotification() { override fun startForegroundNotification() {
execute { execute {
createNotification() createNotification()
}.onSuccess { }.onSuccess {

View File

@ -24,6 +24,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import splitties.init.appCtx import splitties.init.appCtx
import splitties.systemservices.notificationManager
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlin.math.min import kotlin.math.min
@ -59,13 +60,12 @@ class CacheBookService : BaseService() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
isRun = true isRun = true
CacheBook.successDownloadSet.clear() CacheBook.clear()
CacheBook.errorDownloadMap.clear()
lifecycleScope.launch { lifecycleScope.launch {
while (isActive) { while (isActive) {
delay(1000) delay(1000)
notificationContent = CacheBook.downloadSummary notificationContent = CacheBook.downloadSummary
upNotification() upCacheBookNotification()
postEvent(EventBus.UP_DOWNLOAD, "") postEvent(EventBus.UP_DOWNLOAD, "")
} }
} }
@ -90,10 +90,7 @@ class CacheBookService : BaseService() {
override fun onDestroy() { override fun onDestroy() {
isRun = false isRun = false
cachePool.close() cachePool.close()
CacheBook.cacheBookMap.forEach { it.value.stop() } CacheBook.close()
CacheBook.cacheBookMap.clear()
CacheBook.successDownloadSet.clear()
CacheBook.errorDownloadMap.clear()
super.onDestroy() super.onDestroy()
postEvent(EventBus.UP_DOWNLOAD, "") postEvent(EventBus.UP_DOWNLOAD, "")
} }
@ -134,7 +131,7 @@ class CacheBookService : BaseService() {
} }
cacheBook.addDownload(start, end2) cacheBook.addDownload(start, end2)
notificationContent = CacheBook.downloadSummary notificationContent = CacheBook.downloadSummary
upNotification() upCacheBookNotification()
if (downloadJob == null) { if (downloadJob == null) {
download() download()
} }
@ -175,10 +172,16 @@ class CacheBookService : BaseService() {
} }
} }
private fun upCacheBookNotification() {
notificationBuilder.setContentText(notificationContent)
val notification = notificationBuilder.build()
notificationManager.notify(NotificationId.CacheBookService, notification)
}
/** /**
* 更新通知 * 更新通知
*/ */
override fun upNotification() { override fun startForegroundNotification() {
notificationBuilder.setContentText(notificationContent) notificationBuilder.setContentText(notificationContent)
val notification = notificationBuilder.build() val notification = notificationBuilder.build()
startForeground(NotificationId.CacheBookService, notification) startForeground(NotificationId.CacheBookService, notification)

View File

@ -72,7 +72,7 @@ class CheckSourceService : BaseService() {
check(it) check(it)
} }
IntentAction.resume -> upNotification() IntentAction.resume -> startForegroundNotification()
IntentAction.stop -> stopSelf() IntentAction.stop -> stopSelf()
} }
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
@ -96,7 +96,7 @@ class CheckSourceService : BaseService() {
processIndex = 0 processIndex = 0
threadCount = min(allIds.size, threadCount) threadCount = min(allIds.size, threadCount)
notificationMsg = getString(R.string.progress_show, "", 0, allIds.size) notificationMsg = getString(R.string.progress_show, "", 0, allIds.size)
upNotification() startForegroundNotification()
for (i in 0 until threadCount) { for (i in 0 until threadCount) {
check() check()
} }
@ -252,7 +252,7 @@ class CheckSourceService : BaseService() {
checkedIds.add(sourceUrl) checkedIds.add(sourceUrl)
notificationMsg = notificationMsg =
getString(R.string.progress_show, sourceName, checkedIds.size, allIds.size) getString(R.string.progress_show, sourceName, checkedIds.size, allIds.size)
upNotification() startForegroundNotification()
if (processIndex > allIds.size + threadCount - 1) { if (processIndex > allIds.size + threadCount - 1) {
stopSelf() stopSelf()
} }
@ -262,7 +262,7 @@ class CheckSourceService : BaseService() {
/** /**
* 更新通知 * 更新通知
*/ */
override fun upNotification() { override fun startForegroundNotification() {
notificationBuilder.setContentText(notificationMsg) notificationBuilder.setContentText(notificationMsg)
notificationBuilder.setProgress(allIds.size, checkedIds.size, false) notificationBuilder.setProgress(allIds.size, checkedIds.size, false)
postEvent(EventBus.CHECK_SOURCE, notificationMsg) postEvent(EventBus.CHECK_SOURCE, notificationMsg)

View File

@ -223,7 +223,7 @@ class DownloadService : BaseService() {
} }
} }
override fun upNotification() { override fun startForegroundNotification() {
val notification = NotificationCompat.Builder(this, AppConst.channelIdDownload) val notification = NotificationCompat.Builder(this, AppConst.channelIdDownload)
.setSmallIcon(R.drawable.ic_download) .setSmallIcon(R.drawable.ic_download)
.setSubText(getString(R.string.action_download)) .setSubText(getString(R.string.action_download))

View File

@ -50,12 +50,19 @@ import io.legado.app.utils.readText
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 io.legado.app.utils.writeBytes import io.legado.app.utils.writeBytes
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Deferred import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers.Default
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.coroutineScope
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.withIndex
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.ag2s.epublib.domain.Author import me.ag2s.epublib.domain.Author
import me.ag2s.epublib.domain.Date import me.ag2s.epublib.domain.Date
@ -133,7 +140,7 @@ class ExportBookService : BaseService() {
} }
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
override fun upNotification() { override fun startForegroundNotification() {
val notification = NotificationCompat.Builder(this, AppConst.channelIdDownload) val notification = NotificationCompat.Builder(this, AppConst.channelIdDownload)
.setSmallIcon(R.drawable.ic_export) .setSmallIcon(R.drawable.ic_export)
.setSubText(getString(R.string.export_book)) .setSubText(getString(R.string.export_book))
@ -322,15 +329,23 @@ class ExportBookService : BaseService() {
}" }"
append(qy, null) append(qy, null)
if (AppConfig.parallelExportBook) { if (AppConfig.parallelExportBook) {
val oc = coroutineScope {
OrderCoroutine<Pair<String, ArrayList<SrcData>?>>(AppConfig.threadCount) flow {
appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter -> appDb.bookChapterDao.getChapterList(book.bookUrl).forEach { chapter ->
oc.submit { getExportData(book, chapter, contentProcessor, useReplace) } val task = async(Default, start = CoroutineStart.LAZY) {
} getExportData(book, chapter, contentProcessor, useReplace)
oc.collect { index, result -> }
postEvent(EventBus.EXPORT_BOOK, book.bookUrl) emit(task)
exportProgress[book.bookUrl] = index }
append.invoke(result.first, result.second) }.onEach { it.start() }
.buffer(AppConfig.threadCount)
.map { it.await() }
.withIndex()
.collect { (index, result) ->
postEvent(EventBus.EXPORT_BOOK, book.bookUrl)
exportProgress[book.bookUrl] = index
append.invoke(result.first, result.second)
}
} }
} else { } else {
appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter -> appDb.bookChapterDao.getChapterList(book.bookUrl).forEachIndexed { index, chapter ->

View File

@ -80,11 +80,11 @@ class WebService : BaseService() {
if (address == null) { if (address == null) {
hostAddress = getString(R.string.network_connection_unavailable) hostAddress = getString(R.string.network_connection_unavailable)
notificationContent = hostAddress notificationContent = hostAddress
upNotification() startForegroundNotification()
} else { } else {
hostAddress = getString(R.string.http_ip, address.hostAddress, getPort()) hostAddress = getString(R.string.http_ip, address.hostAddress, getPort())
notificationContent = hostAddress notificationContent = hostAddress
upNotification() startForegroundNotification()
} }
postEvent(EventBus.WEB_SERVICE, hostAddress) postEvent(EventBus.WEB_SERVICE, hostAddress)
} }
@ -142,7 +142,7 @@ class WebService : BaseService() {
isRun = true isRun = true
postEvent(EventBus.WEB_SERVICE, hostAddress) postEvent(EventBus.WEB_SERVICE, hostAddress)
notificationContent = hostAddress notificationContent = hostAddress
upNotification() startForegroundNotification()
} catch (e: IOException) { } catch (e: IOException) {
toastOnUi(e.localizedMessage ?: "") toastOnUi(e.localizedMessage ?: "")
e.printOnDebug() e.printOnDebug()
@ -165,7 +165,7 @@ class WebService : BaseService() {
/** /**
* 更新通知 * 更新通知
*/ */
override fun upNotification() { override fun startForegroundNotification() {
val builder = NotificationCompat.Builder(this, AppConst.channelIdWeb) val builder = NotificationCompat.Builder(this, AppConst.channelIdWeb)
.setSmallIcon(R.drawable.ic_web_service_noti) .setSmallIcon(R.drawable.ic_web_service_noti)
.setOngoing(true) .setOngoing(true)