pull/48/head
kunfei 5 years ago
parent 8260ba9a34
commit 72331a5423
  1. 4
      app/src/main/java/io/legado/app/constant/Action.kt
  2. 2
      app/src/main/java/io/legado/app/constant/Bus.kt
  3. 1
      app/src/main/java/io/legado/app/help/http/AjaxWebView.kt
  4. 123
      app/src/main/java/io/legado/app/service/AudioPlayService.kt
  5. 32
      app/src/main/java/io/legado/app/service/help/AudioPlay.kt
  6. 30
      app/src/main/java/io/legado/app/ui/audio/AudioPlayActivity.kt
  7. 149
      app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt
  8. 6
      app/src/main/res/layout/activity_audio_play.xml

@ -12,4 +12,8 @@ object Action {
const val nextParagraph = "nextParagraph"
const val upTtsSpeechRate = "upTtsSpeechRate"
const val adjustProgress = "adjustProgress"
const val prev = "prev"
const val next = "next"
const val moveTo = "moveTo"
const val init = "init"
}

@ -14,7 +14,7 @@ object Bus {
const val UP_CONFIG = "upConfig"
const val OPEN_CHAPTER = "openChapter"
const val REPLACE = "replace"
const val AUDIO_NEXT = "audioNext"
const val AUDIO_SUB_TITLE = "audioSubTitle"
const val AUDIO_STATE = "audioState"
const val AUDIO_PROGRESS = "audioProgress"
const val AUDIO_SIZE = "audioSize"

@ -197,6 +197,7 @@ class AjaxWebView {
return@evaluateJavascript
}
retry++
handler.removeCallbacks(this)
handler.postDelayed(this, 1000)
}
}

@ -20,11 +20,15 @@ import io.legado.app.constant.Action
import io.legado.app.constant.AppConst
import io.legado.app.constant.Bus
import io.legado.app.constant.Status
import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BookHelp
import io.legado.app.help.IntentHelp
import io.legado.app.help.MediaHelp
import io.legado.app.receiver.MediaButtonReceiver
import io.legado.app.service.help.AudioPlay
import io.legado.app.utils.LogUtils
import io.legado.app.utils.postEvent
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import org.jetbrains.anko.toast
@ -72,14 +76,16 @@ class AudioPlayService : BaseService(),
intent?.action?.let { action ->
when (action) {
Action.play -> {
title = intent.getStringExtra("title") ?: ""
subtitle = intent.getStringExtra("subtitle") ?: ""
position = intent.getIntExtra("position", 0)
url = intent.getStringExtra("url")
play()
AudioPlay.book?.let {
title = it.name
position = it.durChapterPos
loadContent(it.durChapterIndex)
}
}
Action.pause -> pause(true)
Action.resume -> resume()
Action.prev -> moveToPrev()
Action.next -> moveToNext()
Action.addTimer -> addTimer()
Action.setTimer -> setTimer(intent.getIntExtra("minute", 0))
Action.adjustProgress -> adjustProgress(intent.getIntExtra("position", position))
@ -102,6 +108,7 @@ class AudioPlayService : BaseService(),
}
private fun play() {
postEvent(Bus.AUDIO_SUB_TITLE, subtitle)
upNotification()
if (requestFocus()) {
try {
@ -176,7 +183,7 @@ class AudioPlayService : BaseService(),
*/
override fun onCompletion(mp: MediaPlayer?) {
handler.removeCallbacks(mpRunnable)
postEvent(Bus.AUDIO_NEXT, 1)
moveToNext()
}
private fun setTimer(minute: Int) {
@ -207,6 +214,110 @@ class AudioPlayService : BaseService(),
handler.postDelayed(mpRunnable, 1000)
}
private fun loadContent(index: Int) {
AudioPlay.book?.let { book ->
if (addLoading(index)) {
launch(IO) {
App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter ->
BookHelp.getContent(book, chapter)?.let {
contentLoadFinish(chapter, it)
removeLoading(chapter.index)
} ?: download(chapter)
} ?: removeLoading(index)
}
}
}
}
private fun download(chapter: BookChapter) {
AudioPlay.book?.let { book ->
AudioPlay.webBook?.getContent(book, chapter, scope = this)
?.onSuccess(IO) { content ->
if (content.isNullOrEmpty()) {
contentLoadFinish(chapter, getString(R.string.content_empty))
removeLoading(chapter.index)
} else {
BookHelp.saveContent(book, chapter, content)
contentLoadFinish(chapter, content)
removeLoading(chapter.index)
}
}?.onError {
contentLoadFinish(chapter, it.localizedMessage)
removeLoading(chapter.index)
}
}
}
private fun addLoading(index: Int): Boolean {
synchronized(this) {
if (AudioPlay.loadingChapters.contains(index)) return false
AudioPlay.loadingChapters.add(index)
return true
}
}
private fun removeLoading(index: Int) {
synchronized(this) {
AudioPlay.loadingChapters.remove(index)
}
}
/**
*
*/
private fun contentLoadFinish(chapter: BookChapter, content: String) {
if (chapter.index == AudioPlay.durChapterIndex) {
subtitle = chapter.title
url = content
play()
}
}
fun moveToPrev() {
if (AudioPlay.durChapterIndex > 0) {
AudioPlay.durChapterIndex--
AudioPlay.durPageIndex = 0
AudioPlay.book?.durChapterIndex = AudioPlay.durChapterIndex
saveRead()
position = 0
loadContent(AudioPlay.durChapterIndex)
}
}
fun moveToNext() {
if (AudioPlay.durChapterIndex < AudioPlay.chapterSize - 1) {
AudioPlay.durChapterIndex++
AudioPlay.durPageIndex = 0
AudioPlay.book?.durChapterIndex = AudioPlay.durChapterIndex
saveRead()
position = 0
loadContent(AudioPlay.durChapterIndex)
} else {
stopSelf()
}
}
private fun saveRead() {
launch(IO) {
AudioPlay.book?.let { book ->
book.lastCheckCount = 0
book.durChapterTime = System.currentTimeMillis()
book.durChapterIndex = AudioPlay.durChapterIndex
book.durChapterPos = AudioPlay.durPageIndex
App.db.bookDao().update(book)
}
}
}
fun saveProgress() {
launch(IO) {
AudioPlay.book?.let {
App.db.bookDao().upProgress(it.bookUrl, AudioPlay.durPageIndex)
}
}
}
/**
* 定时
*/

@ -7,7 +7,6 @@ import io.legado.app.constant.Action
import io.legado.app.data.entities.Book
import io.legado.app.model.WebBook
import io.legado.app.service.AudioPlayService
import io.legado.app.ui.audio.AudioPlayViewModel
object AudioPlay {
var titleData = MutableLiveData<String>()
@ -15,19 +14,14 @@ object AudioPlay {
var book: Book? = null
var inBookshelf = false
var chapterSize = 0
var callBack: AudioPlayViewModel.CallBack? = null
var durChapterIndex = 0
var durPageIndex = 0
var webBook: WebBook? = null
val loadingChapters = arrayListOf<Int>()
fun play(context: Context, title: String?, subtitle: String, url: String, position: Int) {
fun play(context: Context) {
val intent = Intent(context, AudioPlayService::class.java)
intent.action = Action.play
intent.putExtra("title", title)
intent.putExtra("subtitle", subtitle)
intent.putExtra("url", url)
intent.putExtra("position", position)
context.startService(intent)
}
@ -63,4 +57,28 @@ object AudioPlay {
context.startService(intent)
}
}
fun prev(context: Context) {
if (AudioPlayService.isRun) {
val intent = Intent(context, AudioPlayService::class.java)
intent.action = Action.prev
context.startService(intent)
}
}
fun next(context: Context) {
if (AudioPlayService.isRun) {
val intent = Intent(context, AudioPlayService::class.java)
intent.action = Action.next
context.startService(intent)
}
}
fun moveTo(context: Context, index: Int) {
if (AudioPlayService.isRun) {
val intent = Intent(context, AudioPlayService::class.java)
intent.action = Action.moveTo
context.startService(intent)
}
}
}

@ -13,7 +13,6 @@ import io.legado.app.R
import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.Bus
import io.legado.app.constant.Status
import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BlurTransformation
import io.legado.app.help.ImageLoader
import io.legado.app.help.storage.Backup
@ -35,8 +34,7 @@ import org.jetbrains.anko.sdk27.listeners.onLongClick
import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult
class AudioPlayActivity : VMBaseActivity<AudioPlayViewModel>(R.layout.activity_audio_play),
AudioPlayViewModel.CallBack {
class AudioPlayActivity : VMBaseActivity<AudioPlayViewModel>(R.layout.activity_audio_play) {
override val viewModel: AudioPlayViewModel
get() = getViewModel(AudioPlayViewModel::class.java)
@ -62,10 +60,10 @@ class AudioPlayActivity : VMBaseActivity<AudioPlayViewModel>(R.layout.activity_a
true
}
iv_skip_next.onClick {
viewModel.moveToNext()
AudioPlay.next(this)
}
iv_skip_previous.onClick {
viewModel.moveToPrev()
AudioPlay.prev(this)
}
player_progress.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
@ -113,21 +111,10 @@ class AudioPlayActivity : VMBaseActivity<AudioPlayViewModel>(R.layout.activity_a
when (status) {
Status.PLAY -> AudioPlay.pause(this)
Status.PAUSE -> AudioPlay.resume(this)
else -> viewModel.loadContent(AudioPlay.durChapterIndex)
else -> AudioPlay.play(this)
}
}
override fun contentLoadFinish(bookChapter: BookChapter, content: String) {
AudioPlay.play(
this,
AudioPlay.book?.name,
bookChapter.title,
content,
AudioPlay.durPageIndex
)
viewModel.loadContent(AudioPlay.durChapterIndex + 1)
}
override fun finish() {
AudioPlay.book?.let {
if (!AudioPlay.inBookshelf) {
@ -160,7 +147,7 @@ class AudioPlayActivity : VMBaseActivity<AudioPlayViewModel>(R.layout.activity_a
when (requestCode) {
requestCodeChapter -> data?.getIntExtra("index", AudioPlay.durChapterIndex)?.let {
if (it != AudioPlay.durChapterIndex) {
viewModel.loadContent(it)
AudioPlay.moveTo(this, it)
}
}
}
@ -171,9 +158,6 @@ class AudioPlayActivity : VMBaseActivity<AudioPlayViewModel>(R.layout.activity_a
observeEvent<Boolean>(Bus.AUDIO_PLAY_BUTTON) {
playButton()
}
observeEvent<Int>(Bus.AUDIO_NEXT) {
viewModel.moveToNext()
}
observeEvent<Int>(Bus.AUDIO_STATE) {
status = it
if (status == Status.PLAY) {
@ -186,12 +170,14 @@ class AudioPlayActivity : VMBaseActivity<AudioPlayViewModel>(R.layout.activity_a
AudioPlay.durPageIndex = it
if (!adjustProgress) player_progress.progress = it
tv_dur_time.text = DateFormatUtils.format(it.toLong(), "mm:ss")
viewModel.saveProgress()
}
observeEventSticky<Int>(Bus.AUDIO_SIZE) {
player_progress.max = it
tv_all_time.text = DateFormatUtils.format(it.toLong(), "mm:ss")
}
observeEventSticky<String>(Bus.AUDIO_SUB_TITLE) {
tv_sub_title.text = it
}
}
}

@ -10,16 +10,6 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BookHelp
import io.legado.app.model.WebBook
import io.legado.app.service.help.AudioPlay
import io.legado.app.service.help.AudioPlay.book
import io.legado.app.service.help.AudioPlay.callBack
import io.legado.app.service.help.AudioPlay.chapterSize
import io.legado.app.service.help.AudioPlay.coverData
import io.legado.app.service.help.AudioPlay.durChapterIndex
import io.legado.app.service.help.AudioPlay.durPageIndex
import io.legado.app.service.help.AudioPlay.inBookshelf
import io.legado.app.service.help.AudioPlay.loadingChapters
import io.legado.app.service.help.AudioPlay.titleData
import io.legado.app.service.help.AudioPlay.webBook
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@ -27,20 +17,20 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
fun initData(intent: Intent) {
execute {
inBookshelf = intent.getBooleanExtra("inBookshelf", true)
AudioPlay.inBookshelf = intent.getBooleanExtra("inBookshelf", true)
val bookUrl = intent.getStringExtra("bookUrl")
book = if (!bookUrl.isNullOrEmpty()) {
AudioPlay.book = if (!bookUrl.isNullOrEmpty()) {
App.db.bookDao().getBook(bookUrl)
} else {
App.db.bookDao().lastReadBook
}
book?.let { book ->
titleData.postValue(book.name)
coverData.postValue(book.getDisplayCover())
durChapterIndex = book.durChapterIndex
durPageIndex = book.durChapterPos
AudioPlay.book?.let { book ->
AudioPlay.titleData.postValue(book.name)
AudioPlay.coverData.postValue(book.getDisplayCover())
AudioPlay.durChapterIndex = book.durChapterIndex
AudioPlay.durPageIndex = book.durChapterPos
App.db.bookSourceDao().getBookSource(book.origin)?.let {
webBook = WebBook(it)
AudioPlay.webBook = WebBook(it)
}
val count = App.db.bookChapterDao().getChapterCount(book.bookUrl)
if (count == 0) {
@ -50,10 +40,10 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
loadChapterList(book)
}
} else {
if (durChapterIndex > count - 1) {
durChapterIndex = count - 1
if (AudioPlay.durChapterIndex > count - 1) {
AudioPlay.durChapterIndex = count - 1
}
chapterSize = count
AudioPlay.chapterSize = count
}
}
saveRead()
@ -65,7 +55,7 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null
) {
execute {
webBook?.getBookInfo(book, this)
AudioPlay.webBook?.getBookInfo(book, this)
?.onSuccess {
loadChapterList(book, changeDruChapterIndex)
}
@ -77,12 +67,12 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null
) {
execute {
webBook?.getChapterList(book, this)
AudioPlay.webBook?.getChapterList(book, this)
?.onSuccess(Dispatchers.IO) { cList ->
if (!cList.isNullOrEmpty()) {
if (changeDruChapterIndex == null) {
App.db.bookChapterDao().insert(*cList.toTypedArray())
chapterSize = cList.size
AudioPlay.chapterSize = cList.size
} else {
changeDruChapterIndex(cList)
}
@ -95,74 +85,18 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
}
}
fun loadContent(index: Int) {
book?.let { book ->
if (addLoading(index)) {
execute {
App.db.bookChapterDao().getChapter(book.bookUrl, index)?.let { chapter ->
BookHelp.getContent(book, chapter)?.let {
contentLoadFinish(chapter, it)
removeLoading(chapter.index)
} ?: download(chapter)
} ?: removeLoading(index)
}.onError {
removeLoading(index)
}
}
}
}
private fun download(chapter: BookChapter) {
book?.let { book ->
webBook?.getContent(book, chapter, scope = this)
?.onSuccess(Dispatchers.IO) { content ->
if (content.isNullOrEmpty()) {
contentLoadFinish(chapter, context.getString(R.string.content_empty))
removeLoading(chapter.index)
} else {
BookHelp.saveContent(book, chapter, content)
contentLoadFinish(chapter, content)
removeLoading(chapter.index)
}
}?.onError {
contentLoadFinish(chapter, it.localizedMessage)
removeLoading(chapter.index)
}
}
}
private fun addLoading(index: Int): Boolean {
synchronized(this) {
if (loadingChapters.contains(index)) return false
loadingChapters.add(index)
return true
}
}
private fun removeLoading(index: Int) {
synchronized(this) {
loadingChapters.remove(index)
}
}
private fun contentLoadFinish(chapter: BookChapter, content: String) {
if (chapter.index == durChapterIndex) {
callBack?.contentLoadFinish(chapter, content)
}
}
fun changeTo(book1: Book) {
execute {
book?.let {
AudioPlay.book?.let {
App.db.bookDao().delete(it.bookUrl)
}
withContext(Dispatchers.Main) {
}
App.db.bookDao().insert(book1)
book = book1
AudioPlay.book = book1
App.db.bookSourceDao().getBookSource(book1.origin)?.let {
webBook = WebBook(it)
AudioPlay.webBook = WebBook(it)
}
if (book1.tocUrl.isEmpty()) {
loadBookInfo(book1) { upChangeDurChapterIndex(book1, it) }
@ -174,64 +108,34 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
private fun upChangeDurChapterIndex(book: Book, chapters: List<BookChapter>) {
execute {
durChapterIndex = BookHelp.getDurChapterIndexByChapterTitle(
AudioPlay.durChapterIndex = BookHelp.getDurChapterIndexByChapterTitle(
book.durChapterTitle,
book.durChapterIndex,
chapters
)
book.durChapterIndex = durChapterIndex
book.durChapterTitle = chapters[durChapterIndex].title
book.durChapterIndex = AudioPlay.durChapterIndex
book.durChapterTitle = chapters[AudioPlay.durChapterIndex].title
App.db.bookDao().update(book)
App.db.bookChapterDao().insert(*chapters.toTypedArray())
chapterSize = chapters.size
}
}
fun moveToPrev() {
if (durChapterIndex > 0) {
durChapterIndex--
durPageIndex = 0
book?.durChapterIndex = durChapterIndex
saveRead()
loadContent(durChapterIndex)
}
}
fun moveToNext() {
if (durChapterIndex < chapterSize - 1) {
durChapterIndex++
durPageIndex = 0
book?.durChapterIndex = durChapterIndex
saveRead()
loadContent(durChapterIndex)
} else {
AudioPlay.stop(context)
AudioPlay.chapterSize = chapters.size
}
}
private fun saveRead() {
execute {
book?.let { book ->
AudioPlay.book?.let { book ->
book.lastCheckCount = 0
book.durChapterTime = System.currentTimeMillis()
book.durChapterIndex = durChapterIndex
book.durChapterPos = durPageIndex
book.durChapterIndex = AudioPlay.durChapterIndex
book.durChapterPos = AudioPlay.durPageIndex
App.db.bookDao().update(book)
}
}
}
fun saveProgress() {
execute {
book?.let {
App.db.bookDao().upProgress(it.bookUrl, durPageIndex)
}
}
}
fun removeFromBookshelf(success: (() -> Unit)?) {
execute {
book?.let {
AudioPlay.book?.let {
App.db.bookDao().delete(it.bookUrl)
}
}.onSuccess {
@ -239,7 +143,4 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
}
}
interface CallBack {
fun contentLoadFinish(bookChapter: BookChapter, content: String)
}
}

@ -42,6 +42,12 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title_bar" />
<TextView
android:id="@+id/tv_sub_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/ll_player_progress" />
<LinearLayout
android:id="@+id/ll_player_progress"
android:layout_width="match_parent"

Loading…
Cancel
Save