pull/1282/head
gedoor 3 years ago
parent 531a3513d1
commit 2f638af692
  1. 11
      app/src/main/java/io/legado/app/help/IntentHelp.kt
  2. 95
      app/src/main/java/io/legado/app/service/AudioPlayService.kt
  3. 14
      app/src/main/java/io/legado/app/service/BaseReadAloudService.kt
  4. 22
      app/src/main/java/io/legado/app/service/CacheBookService.kt
  5. 17
      app/src/main/java/io/legado/app/service/DownloadService.kt
  6. 6
      app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt

@ -54,4 +54,15 @@ object IntentHelp {
configIntent.invoke(intent)
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
inline fun <reified T> broadcastPendingIntent(
context: Context,
action: String,
configIntent: Intent.() -> Unit = {}
): PendingIntent? {
val intent = Intent(context, T::class.java)
intent.action = action
configIntent.invoke(intent)
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)
}
}

@ -1,5 +1,6 @@
package io.legado.app.service
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
@ -10,8 +11,6 @@ import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import androidx.core.app.NotificationCompat
@ -29,13 +28,12 @@ import io.legado.app.help.MediaHelp
import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.receiver.MediaButtonReceiver
import io.legado.app.service.help.AudioPlay
import io.legado.app.service.help.ReadAloud
import io.legado.app.ui.book.audio.AudioPlayActivity
import io.legado.app.utils.postEvent
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import splitties.init.appCtx
class AudioPlayService : BaseService(),
@ -50,7 +48,6 @@ class AudioPlayService : BaseService(),
var timeMinute: Int = 0
}
private val handler = Handler(Looper.getMainLooper())
private lateinit var audioManager: AudioManager
private var mFocusRequest: AudioFocusRequestCompat? = null
private var title: String = ""
@ -60,8 +57,8 @@ class AudioPlayService : BaseService(),
private var broadcastReceiver: BroadcastReceiver? = null
private var url: String = ""
private var position = 0
private val dsRunnable: Runnable = Runnable { doDs() }
private var mpRunnable: Runnable = Runnable { upPlayProgress() }
private var dsJob: Job? = null
private var upPlayProgressJob: Job? = null
private var playSpeed: Float = 1f
override fun onCreate() {
@ -108,8 +105,6 @@ class AudioPlayService : BaseService(),
override fun onDestroy() {
super.onDestroy()
isRun = false
handler.removeCallbacks(dsRunnable)
handler.removeCallbacks(mpRunnable)
mediaPlayer.release()
mediaSessionCompat?.release()
unregisterReceiver(broadcastReceiver)
@ -130,7 +125,7 @@ class AudioPlayService : BaseService(),
val uri = Uri.parse(analyzeUrl.url)
mediaPlayer.setDataSource(this, uri, analyzeUrl.headerMap)
mediaPlayer.prepareAsync()
handler.removeCallbacks(mpRunnable)
upPlayProgressJob?.cancel()
}.onFailure {
it.printStackTrace()
launch {
@ -147,7 +142,7 @@ class AudioPlayService : BaseService(),
} else {
try {
AudioPlayService.pause = pause
handler.removeCallbacks(mpRunnable)
upPlayProgressJob?.cancel()
position = mediaPlayer.currentPosition
if (mediaPlayer.isPlaying) mediaPlayer.pause()
upMediaSessionPlaybackState(PlaybackStateCompat.STATE_PAUSED)
@ -167,8 +162,7 @@ class AudioPlayService : BaseService(),
mediaPlayer.start()
mediaPlayer.seekTo(position)
}
handler.removeCallbacks(mpRunnable)
handler.postDelayed(mpRunnable, 1000)
upPlayProgress()
upMediaSessionPlaybackState(PlaybackStateCompat.STATE_PLAYING)
AudioPlay.status = Status.PLAY
postEvent(EventBus.AUDIO_STATE, Status.PLAY)
@ -213,8 +207,7 @@ class AudioPlayService : BaseService(),
AudioPlay.status = Status.PLAY
postEvent(EventBus.AUDIO_STATE, Status.PLAY)
postEvent(EventBus.AUDIO_SIZE, mediaPlayer.duration)
handler.removeCallbacks(mpRunnable)
handler.post(mpRunnable)
upPlayProgress()
AudioPlay.saveDurChapter(mediaPlayer.duration.toLong())
}
@ -234,40 +227,61 @@ class AudioPlayService : BaseService(),
* 播放结束
*/
override fun onCompletion(mp: MediaPlayer) {
handler.removeCallbacks(mpRunnable)
upPlayProgressJob?.cancel()
AudioPlay.next(this)
}
private fun setTimer(minute: Int) {
timeMinute = minute
if (minute > 0) {
handler.removeCallbacks(dsRunnable)
handler.postDelayed(dsRunnable, 60000)
}
upNotification()
doDs()
}
private fun addTimer() {
if (timeMinute == 60) {
timeMinute = 0
handler.removeCallbacks(dsRunnable)
} else {
timeMinute += 10
if (timeMinute > 60) timeMinute = 60
handler.removeCallbacks(dsRunnable)
handler.postDelayed(dsRunnable, 60000)
}
doDs()
}
/**
* 定时
*/
private fun doDs() {
postEvent(EventBus.TTS_DS, timeMinute)
upNotification()
dsJob?.cancel()
dsJob = launch {
while (isActive) {
delay(60000)
if (!pause) {
if (timeMinute >= 0) {
timeMinute--
}
if (timeMinute == 0) {
ReadAloud.stop(this@AudioPlayService)
}
}
postEvent(EventBus.TTS_DS, timeMinute)
upNotification()
}
}
}
/**
* 更新播放进度
*/
private fun upPlayProgress() {
upPlayProgressJob?.cancel()
upPlayProgressJob = launch {
while (isActive) {
saveProgress()
postEvent(EventBus.AUDIO_PROGRESS, mediaPlayer.currentPosition)
handler.postDelayed(mpRunnable, 1000)
delay(1000)
}
}
}
private fun loadContent() = with(AudioPlay) {
@ -332,22 +346,6 @@ class AudioPlayService : BaseService(),
}
}
/**
* 定时
*/
private fun doDs() {
if (!pause) {
timeMinute--
if (timeMinute == 0) {
stopSelf()
} else if (timeMinute > 0) {
handler.postDelayed(dsRunnable, 60000)
}
}
postEvent(EventBus.TTS_DS, timeMinute)
upNotification()
}
/**
* 更新媒体状态
*/
@ -363,6 +361,7 @@ class AudioPlayService : BaseService(),
/**
* 初始化MediaSession, 注册多媒体按钮
*/
@SuppressLint("UnspecifiedImmutableFlag")
private fun initMediaSession() {
mediaSessionCompat = MediaSessionCompat(this, "readAloud")
mediaSessionCompat?.setCallback(object : MediaSessionCompat.Callback() {
@ -371,15 +370,9 @@ class AudioPlayService : BaseService(),
}
})
mediaSessionCompat?.setMediaButtonReceiver(
PendingIntent.getBroadcast(
this, 0,
Intent(
Intent.ACTION_MEDIA_BUTTON,
null,
appCtx,
MediaButtonReceiver::class.java
),
PendingIntent.FLAG_CANCEL_CURRENT
IntentHelp.broadcastPendingIntent<MediaButtonReceiver>(
this,
Intent.ACTION_MEDIA_BUTTON
)
)
mediaSessionCompat?.isActive = true

@ -31,7 +31,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import splitties.init.appCtx
abstract class BaseReadAloudService : BaseService(),
AudioManager.OnAudioFocusChangeListener {
@ -209,7 +208,6 @@ abstract class BaseReadAloudService : BaseService(),
dsJob = launch {
while (isActive) {
delay(60000)
if (isActive) {
if (!pause) {
if (timeMinute >= 0) {
timeMinute--
@ -223,7 +221,6 @@ abstract class BaseReadAloudService : BaseService(),
}
}
}
}
/**
* @return 音频焦点
@ -259,16 +256,9 @@ abstract class BaseReadAloudService : BaseService(),
}
})
mediaSessionCompat.setMediaButtonReceiver(
PendingIntent.getBroadcast(
IntentHelp.broadcastPendingIntent<MediaButtonReceiver>(
this,
0,
Intent(
Intent.ACTION_MEDIA_BUTTON,
null,
appCtx,
MediaButtonReceiver::class.java
),
PendingIntent.FLAG_CANCEL_CURRENT
Intent.ACTION_MEDIA_BUTTON
)
)
mediaSessionCompat.isActive = true

@ -1,8 +1,6 @@
package io.legado.app.service
import android.content.Intent
import android.os.Handler
import android.os.Looper
import androidx.core.app.NotificationCompat
import io.legado.app.R
import io.legado.app.base.BaseService
@ -22,7 +20,9 @@ import io.legado.app.service.help.CacheBook
import io.legado.app.utils.postEvent
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import splitties.init.appCtx
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet
@ -34,8 +34,6 @@ class CacheBookService : BaseService() {
private var cachePool =
Executors.newFixedThreadPool(min(threadCount, 8)).asCoroutineDispatcher()
private var tasks = CompositeCoroutine()
private val handler = Handler(Looper.getMainLooper())
private var runnable: Runnable = Runnable { upDownload() }
private val bookMap = ConcurrentHashMap<String, Book>()
private val webBookMap = ConcurrentHashMap<String, WebBook>()
private val downloadMap = ConcurrentHashMap<String, CopyOnWriteArraySet<BookChapter>>()
@ -63,7 +61,13 @@ class CacheBookService : BaseService() {
override fun onCreate() {
super.onCreate()
upNotification()
handler.postDelayed(runnable, 1000)
launch {
while (isActive) {
delay(1000)
upNotification()
postEvent(EventBus.UP_DOWNLOAD, downloadMap)
}
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
@ -84,7 +88,6 @@ class CacheBookService : BaseService() {
override fun onDestroy() {
tasks.clear()
cachePool.close()
handler.removeCallbacks(runnable)
downloadMap.clear()
finalMap.clear()
super.onDestroy()
@ -252,13 +255,6 @@ class CacheBookService : BaseService() {
stopSelf()
}
private fun upDownload() {
upNotification()
postEvent(EventBus.UP_DOWNLOAD, downloadMap)
handler.removeCallbacks(runnable)
handler.postDelayed(runnable, 1000)
}
private fun upNotification(
downloadCount: DownloadCount,
totalCount: Int?,

@ -7,8 +7,6 @@ import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import android.os.Handler
import android.os.Looper
import androidx.core.app.NotificationCompat
import androidx.core.content.FileProvider
import io.legado.app.R
@ -19,6 +17,9 @@ import io.legado.app.help.IntentHelp
import io.legado.app.utils.RealPathUtil
import io.legado.app.utils.msg
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import splitties.systemservices.downloadManager
import java.io.File
@ -27,11 +28,7 @@ class DownloadService : BaseService() {
private val downloads = hashMapOf<Long, String>()
private val completeDownloads = hashSetOf<Long>()
private val handler = Handler(Looper.getMainLooper())
private val runnable = Runnable {
checkDownloadState()
}
private var upStateJob: Job? = null
private val downloadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
queryState()
@ -78,9 +75,11 @@ class DownloadService : BaseService() {
}
private fun checkDownloadState() {
handler.removeCallbacks(runnable)
upStateJob?.cancel()
upStateJob = launch {
queryState()
handler.postDelayed(runnable, 1000)
delay(1000)
}
}
//查询下载进度

@ -707,7 +707,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
delayMillis = 20
}
delay(delayMillis)
if (!menuLayoutIsVisible && isActive) {
if (!menuLayoutIsVisible) {
if (binding.readView.isScroll) {
binding.readView.curPage.scroll(-scrollOffset)
} else {
@ -882,14 +882,12 @@ class ReadBookActivity : ReadBookBaseActivity(),
backupJob?.cancel()
backupJob = launch {
delay(120000)
if (isActive) {
ReadBook.book?.let {
AppWebDav.uploadBookProgress(it)
Backup.autoBack(this@ReadBookActivity)
}
}
}
}
override fun finish() {
ReadBook.book?.let {
@ -997,9 +995,7 @@ class ReadBookActivity : ReadBookBaseActivity(),
if (t > 0) {
keepScreenOn(true)
delay(screenTimeOut)
if (isActive) {
keepScreenOn(false)
}
} else {
keepScreenOn(false)
}

Loading…
Cancel
Save