合并上游更改

感谢:@821938089、@zhongerxll、@youke2580c、@Leroy-X、@Dark-Tide、@lhjgege、@3harmony、@mgz0227
This commit is contained in:
HapeLee committed 2025-09-01 00:57:17 +08:00
1 parent dccb72adab
commit 8eb4881767
87 files changed
+800 -365

No files matched your search

@@ -27,6 +27,7 @@ import io.legato.kazusa.R
import io.legato.kazusa.base.BaseService
import io.legato.kazusa.constant.AppConst
import io.legato.kazusa.constant.AppLog
import io.legato.kazusa.constant.AppPattern
import io.legato.kazusa.constant.EventBus
import io.legato.kazusa.constant.IntentAction
import io.legato.kazusa.constant.NotificationId
@@ -45,9 +46,7 @@ import io.legato.kazusa.ui.book.read.ReadBookActivity
import io.legato.kazusa.ui.book.read.page.entities.TextChapter
import io.legato.kazusa.utils.LogUtils
import io.legato.kazusa.utils.activityPendingIntent
import io.legato.kazusa.utils.broadcastPendingIntent
import io.legato.kazusa.utils.getPrefBoolean
import io.legato.kazusa.utils.isVivoDevice
import io.legato.kazusa.utils.observeEvent
import io.legato.kazusa.utils.observeSharedPreferences
import io.legato.kazusa.utils.postEvent
@@ -326,9 +325,11 @@ abstract class BaseReadAloudService : BaseService(),
private fun prevP() {
if (nowSpeak > 0) {
playStop()
nowSpeak--
readAloudNumber -= contentList[nowSpeak].length + 1 + paragraphStartPos
paragraphStartPos = 0
do {
nowSpeak--
readAloudNumber -= contentList[nowSpeak].length + 1 + paragraphStartPos
paragraphStartPos = 0
} while (contentList[nowSpeak].matches(AppPattern.notReadAloudRegex))
textChapter?.let {
if (readAloudByPage) {
val paragraphs = it.getParagraphs(true)
@@ -358,7 +359,9 @@ abstract class BaseReadAloudService : BaseService(),
val paragraphs = it.getParagraphs(true)
if (!paragraphs[nowSpeak].isParagraphEnd) readAloudNumber--
}
if (readAloudNumber >= it.getReadLength(pageIndex + 1)) {
if (pageIndex + 1 < it.pageSize
&& readAloudNumber >= it.getReadLength(pageIndex + 1)
) {
pageIndex++
ReadBook.moveToNextPage()
}
@@ -443,24 +446,75 @@ abstract class BaseReadAloudService : BaseService(),
PlaybackStateCompat.Builder()
.setActions(MediaHelp.MEDIA_SESSION_ACTIONS)
.setState(state, nowSpeak.toLong(), 1f)
// 为系统媒体控件添加定时按钮
.addCustomAction(
PlaybackStateCompat.CustomAction.Builder(
"ACTION_ADD_TIMER",
getString(R.string.set_timer),
R.drawable.ic_time_add_24dp
).build()
)
.build()
)
}
/**
* 初始化MediaSession, 注册多媒体按钮
*/
/**
* 初始化MediaSession, 注册多媒体按钮
*/
@SuppressLint("UnspecifiedImmutableFlag")
private fun initMediaSession() {
mediaSessionCompat.setCallback(object : MediaSessionCompat.Callback() {
override fun onMediaButtonEvent(mediaButtonEvent: Intent): Boolean {
return MediaButtonReceiver.handleIntent(this@BaseReadAloudService, mediaButtonEvent)
}
})
mediaSessionCompat.setMediaButtonReceiver(
broadcastPendingIntent<MediaButtonReceiver>(Intent.ACTION_MEDIA_BUTTON)
)
mediaSessionCompat.isActive = true
if (getPrefBoolean("systemMediaControlCompatibilityChange")) {
mediaSessionCompat.setCallback(object : MediaSessionCompat.Callback() {
override fun onPlay() {
resumeReadAloud()
}
override fun onPause() {
pauseReadAloud()
}
override fun onSkipToNext() {
if (getPrefBoolean("mediaButtonPerNext", false)) {
nextChapter()
} else {
nextP()
}
}
override fun onSkipToPrevious() {
if (getPrefBoolean("mediaButtonPerNext", false)) {
prevChapter()
} else {
prevP()
}
}
override fun onStop() {
stopSelf()
}
override fun onCustomAction(action: String, extras: Bundle?) {
if (action == "ACTION_ADD_TIMER") addTimer()
}
override fun onMediaButtonEvent(mediaButtonEvent: Intent): Boolean {
return MediaButtonReceiver.handleIntent(
this@BaseReadAloudService, mediaButtonEvent
)
}
})
} else {
mediaSessionCompat.setCallback(object : MediaSessionCompat.Callback() {
override fun onMediaButtonEvent(mediaButtonEvent: Intent): Boolean {
return MediaButtonReceiver.handleIntent(
this@BaseReadAloudService, mediaButtonEvent
)
}
})
}
}
/**
@@ -523,7 +577,7 @@ abstract class BaseReadAloudService : BaseService(),
private fun choiceMediaStyle(): androidx.media.app.NotificationCompat.MediaStyle {
val mediaStyle = androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(1, 2, 4)
if (isVivoDevice) {
if (getPrefBoolean("systemMediaControlCompatibilityChange")) {
//fix #4090 android 14 can not show play control in lock screen
mediaStyle.setMediaSession(mediaSessionCompat.sessionToken)
}
@@ -65,7 +65,6 @@ class CacheBookService : BaseService() {
override fun onCreate() {
super.onCreate()
isRun = true
CacheBook.clear()
lifecycleScope.launch {
while (isActive) {
delay(1000)
@@ -3,6 +3,7 @@ package io.legato.kazusa.service
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.net.Uri
import androidx.core.net.toUri
import androidx.lifecycle.lifecycleScope
import androidx.media3.common.C
import androidx.media3.common.MediaItem
@@ -306,7 +307,7 @@ class HttpReadAloudService : BaseReadAloudService(),
}
private fun createDownloader(factory: CacheDataSource.Factory, fileName: String): Downloader {
val uri = Uri.parse(fileName)
val uri = fileName.toUri()
val request = DownloadRequest.Builder(fileName, uri).build()
return DefaultDownloaderFactory(factory, okHttpClient.dispatcher.executorService)
.createDownloader(request)
@@ -343,17 +344,17 @@ class HttpReadAloudService : BaseReadAloudService(),
val contentType = contentType.substringBefore(";")
val ct = httpTts.contentType
if (contentType == "application/json" || contentType.startsWith("text/")) {
throw NoStackTraceException(response.body!!.string())
throw NoStackTraceException(response.body.string())
} else if (ct?.isNotBlank() == true) {
if (!contentType.matches(ct.toRegex())) {
throw NoStackTraceException(
"TTS服务器返回错误:" + response.body!!.string()
"TTS服务器返回错误:" + response.body.string()
)
}
}
}
coroutineContext.ensureActive()
response.body!!.byteStream().let { stream ->
response.body.byteStream().let { stream ->
downloadErrorNo = 0
return stream
}
@@ -477,12 +478,12 @@ class HttpReadAloudService : BaseReadAloudService(),
val sleep = exoPlayer.duration / speakTextLength
val start = speakTextLength * exoPlayer.currentPosition / exoPlayer.duration
for (i in start..contentList[nowSpeak].length) {
if (readAloudNumber + i > textChapter.getReadLength(pageIndex + 1)) {
if (pageIndex + 1 < textChapter.pageSize
&& readAloudNumber + i > textChapter.getReadLength(pageIndex + 1)
) {
pageIndex++
if (pageIndex < textChapter.pageSize) {
ReadBook.moveToNextPage()
upTtsProgress(readAloudNumber + i.toInt())
}
ReadBook.moveToNextPage()
upTtsProgress(readAloudNumber + i.toInt())
}
delay(sleep)
}
@@ -195,7 +195,9 @@ class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener
if (contentList[nowSpeak].matches(AppPattern.notReadAloudRegex)) {
nextParagraph()
}
if (readAloudNumber + 1 > it.getReadLength(pageIndex + 1)) {
if (pageIndex + 1 < it.pageSize
&& readAloudNumber + 1 > it.getReadLength(pageIndex + 1)
) {
pageIndex++
ReadBook.moveToNextPage()
}
@@ -214,7 +216,9 @@ class TTSReadAloudService : BaseReadAloudService(), TextToSpeech.OnInitListener
"onRangeStart nowSpeak:$nowSpeak pageIndex:$pageIndex utteranceId:$utteranceId start:$start end:$end frame:$frame"
LogUtils.d(TAG, msg)
textChapter?.let {
if (readAloudNumber + start > it.getReadLength(pageIndex + 1)) {
if (pageIndex + 1 < it.pageSize
&& readAloudNumber + start > it.getReadLength(pageIndex + 1)
) {
pageIndex++
ReadBook.moveToNextPage()
upTtsProgress(readAloudNumber + start)