Fixed ChromeCast crashes
This commit is contained in:
parent
9966ddad9d
commit
ed6ca486d6
4 changed files with 21 additions and 73 deletions
|
@ -10,8 +10,7 @@ import com.google.android.gms.cast.MediaStatus
|
||||||
import com.google.android.gms.cast.framework.CastSession
|
import com.google.android.gms.cast.framework.CastSession
|
||||||
import com.google.android.gms.cast.framework.media.RemoteMediaClient
|
import com.google.android.gms.cast.framework.media.RemoteMediaClient
|
||||||
|
|
||||||
class CastPlayer(castSession: CastSession) : Playback,
|
class CastPlayer(castSession: CastSession) : Playback, RemoteMediaClient.Callback() {
|
||||||
RemoteMediaClient.Callback() {
|
|
||||||
|
|
||||||
override val isInitialized: Boolean = true
|
override val isInitialized: Boolean = true
|
||||||
|
|
||||||
|
|
|
@ -203,8 +203,7 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private var queueSaveHandler: QueueSaveHandler? = null
|
|
||||||
private var queueSaveHandlerThread: HandlerThread? = null
|
|
||||||
private var queuesRestored = false
|
private var queuesRestored = false
|
||||||
|
|
||||||
var repeatMode = 0
|
var repeatMode = 0
|
||||||
|
@ -277,12 +276,6 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
playbackManager.setCallbacks(this)
|
playbackManager.setCallbacks(this)
|
||||||
setupMediaSession()
|
setupMediaSession()
|
||||||
|
|
||||||
// queue saving needs to run on a separate thread so that it doesn't block the playback handler
|
|
||||||
// events
|
|
||||||
queueSaveHandlerThread =
|
|
||||||
HandlerThread("QueueSaveHandler", Process.THREAD_PRIORITY_BACKGROUND)
|
|
||||||
queueSaveHandlerThread?.start()
|
|
||||||
queueSaveHandler = QueueSaveHandler(this, queueSaveHandlerThread!!.looper)
|
|
||||||
uiThreadHandler = Handler(Looper.getMainLooper())
|
uiThreadHandler = Handler(Looper.getMainLooper())
|
||||||
registerReceiver(widgetIntentReceiver, IntentFilter(APP_WIDGET_UPDATE))
|
registerReceiver(widgetIntentReceiver, IntentFilter(APP_WIDGET_UPDATE))
|
||||||
registerReceiver(updateFavoriteReceiver, IntentFilter(FAVORITE_STATE_CHANGED))
|
registerReceiver(updateFavoriteReceiver, IntentFilter(FAVORITE_STATE_CHANGED))
|
||||||
|
@ -291,7 +284,7 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
notificationManager = getSystemService()
|
notificationManager = getSystemService()
|
||||||
initNotification()
|
initNotification()
|
||||||
mediaStoreObserver = MediaStoreObserver(this, playerHandler!!)
|
mediaStoreObserver = MediaStoreObserver(this, playerHandler!!)
|
||||||
throttledSeekHandler = ThrottledSeekHandler(this, playerHandler!!)
|
throttledSeekHandler = ThrottledSeekHandler(this, Handler(mainLooper))
|
||||||
contentResolver.registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
contentResolver.registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||||
true,
|
true,
|
||||||
mediaStoreObserver)
|
mediaStoreObserver)
|
||||||
|
@ -798,7 +791,7 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
// Every chromecast method needs to run on main thread or you are greeted with IllegalStateException
|
// Every chromecast method needs to run on main thread or you are greeted with IllegalStateException
|
||||||
// So it will use Main dispatcher
|
// So it will use Main dispatcher
|
||||||
// And by using Default dispatcher for local playback we are reduce the burden of main thread
|
// And by using Default dispatcher for local playback we are reduce the burden of main thread
|
||||||
serviceScope.launch(if(playbackManager.isLocalPlayback) Default else Main) {
|
serviceScope.launch(if (playbackManager.isLocalPlayback) Default else Main) {
|
||||||
openTrackAndPrepareNextAt(position) { success ->
|
openTrackAndPrepareNextAt(position) { success ->
|
||||||
if (success) {
|
if (success) {
|
||||||
play()
|
play()
|
||||||
|
@ -953,17 +946,6 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveQueuesImpl() {
|
|
||||||
MusicPlaybackQueueStore.getInstance(this).saveQueues(playingQueue, originalPlayingQueue)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveState() {
|
|
||||||
saveQueues()
|
|
||||||
savePosition()
|
|
||||||
savePositionInTrack()
|
|
||||||
storage.saveSong(currentSong)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun seek(millis: Int): Int {
|
fun seek(millis: Int): Int {
|
||||||
return try {
|
return try {
|
||||||
|
@ -1105,8 +1087,10 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
// if we are loading it or it won't be updated in the notification
|
// if we are loading it or it won't be updated in the notification
|
||||||
updateMediaSessionMetaData(::updateMediaSessionPlaybackState)
|
updateMediaSessionMetaData(::updateMediaSessionPlaybackState)
|
||||||
serviceScope.launch(IO) {
|
serviceScope.launch(IO) {
|
||||||
savePosition()
|
withContext(Main) {
|
||||||
savePositionInTrack()
|
savePosition()
|
||||||
|
savePositionInTrack()
|
||||||
|
}
|
||||||
val currentSong = currentSong
|
val currentSong = currentSong
|
||||||
HistoryStore.getInstance(this@MusicService).addSongId(currentSong.id)
|
HistoryStore.getInstance(this@MusicService).addSongId(currentSong.id)
|
||||||
if (songPlayCountHelper.shouldBumpPlayCount()) {
|
if (songPlayCountHelper.shouldBumpPlayCount()) {
|
||||||
|
@ -1114,13 +1098,14 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
.bumpPlayCount(songPlayCountHelper.song.id)
|
.bumpPlayCount(songPlayCountHelper.song.id)
|
||||||
}
|
}
|
||||||
songPlayCountHelper.notifySongChanged(currentSong)
|
songPlayCountHelper.notifySongChanged(currentSong)
|
||||||
|
storage.saveSong(currentSong)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QUEUE_CHANGED -> {
|
QUEUE_CHANGED -> {
|
||||||
mediaSession?.setQueueTitle(getString(R.string.now_playing_queue))
|
mediaSession?.setQueueTitle(getString(R.string.now_playing_queue))
|
||||||
mediaSession?.setQueue(playingQueue.toMediaSessionQueue())
|
mediaSession?.setQueue(playingQueue.toMediaSessionQueue())
|
||||||
updateMediaSessionMetaData(::updateMediaSessionPlaybackState) // because playing queue size might have changed
|
updateMediaSessionMetaData(::updateMediaSessionPlaybackState) // because playing queue size might have changed
|
||||||
saveState()
|
saveQueues()
|
||||||
if (playingQueue.size > 0) {
|
if (playingQueue.size > 0) {
|
||||||
prepareNext()
|
prepareNext()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1198,6 +1183,8 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
seek(progress)
|
seek(progress)
|
||||||
if (wasPlaying) {
|
if (wasPlaying) {
|
||||||
play()
|
play()
|
||||||
|
} else {
|
||||||
|
pause()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1247,8 +1234,6 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
private fun releaseResources() {
|
private fun releaseResources() {
|
||||||
playerHandler?.removeCallbacksAndMessages(null)
|
playerHandler?.removeCallbacksAndMessages(null)
|
||||||
musicPlayerHandlerThread?.quitSafely()
|
musicPlayerHandlerThread?.quitSafely()
|
||||||
queueSaveHandler?.removeCallbacksAndMessages(null)
|
|
||||||
queueSaveHandlerThread?.quitSafely()
|
|
||||||
playbackManager.release()
|
playbackManager.release()
|
||||||
mediaSession?.release()
|
mediaSession?.release()
|
||||||
}
|
}
|
||||||
|
@ -1275,8 +1260,10 @@ class MusicService : MediaBrowserServiceCompat(),
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveQueues() {
|
private fun saveQueues() {
|
||||||
queueSaveHandler?.removeMessages(SAVE_QUEUES)
|
serviceScope.launch(IO) {
|
||||||
queueSaveHandler?.sendEmptyMessage(SAVE_QUEUES)
|
MusicPlaybackQueueStore.getInstance(this@MusicService)
|
||||||
|
.saveQueues(playingQueue, originalPlayingQueue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sendChangeInternal(what: String) {
|
private fun sendChangeInternal(what: String) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ class PlaybackManager(val context: Context) {
|
||||||
var playback: Playback? = null
|
var playback: Playback? = null
|
||||||
private var playbackLocation = PlaybackLocation.LOCAL
|
private var playbackLocation = PlaybackLocation.LOCAL
|
||||||
|
|
||||||
val isLocalPlayback get() = playbackLocation== PlaybackLocation.LOCAL
|
val isLocalPlayback get() = playbackLocation == PlaybackLocation.LOCAL
|
||||||
|
|
||||||
val audioSessionId: Int
|
val audioSessionId: Int
|
||||||
get() = if (playback != null) {
|
get() = if (playback != null) {
|
||||||
|
@ -168,14 +168,11 @@ class PlaybackManager(val context: Context) {
|
||||||
playback: Playback,
|
playback: Playback,
|
||||||
onChange: (wasPlaying: Boolean, progress: Int) -> Unit,
|
onChange: (wasPlaying: Boolean, progress: Int) -> Unit,
|
||||||
) {
|
) {
|
||||||
val oldPlayback = playback
|
val oldPlayback = this.playback
|
||||||
val wasPlaying: Boolean = oldPlayback.isPlaying
|
val wasPlaying: Boolean = oldPlayback?.isPlaying == true
|
||||||
val progress: Int = oldPlayback.position()
|
val progress: Int = oldPlayback?.position() ?: 0
|
||||||
|
|
||||||
this.playback = playback
|
this.playback = playback
|
||||||
|
oldPlayback?.stop()
|
||||||
oldPlayback.stop()
|
|
||||||
|
|
||||||
onChange(wasPlaying, progress)
|
onChange(wasPlaying, progress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 Hemanth Savarala.
|
|
||||||
*
|
|
||||||
* Licensed under the GNU General Public License v3
|
|
||||||
*
|
|
||||||
* This is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
||||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
* See the GNU General Public License for more details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package code.name.monkey.retromusic.service
|
|
||||||
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.os.Message
|
|
||||||
import code.name.monkey.retromusic.service.MusicService.Companion.SAVE_QUEUES
|
|
||||||
import java.lang.ref.WeakReference
|
|
||||||
|
|
||||||
internal class QueueSaveHandler(
|
|
||||||
musicService: MusicService,
|
|
||||||
looper: Looper
|
|
||||||
) : Handler(looper) {
|
|
||||||
private val service: WeakReference<MusicService> = WeakReference(musicService)
|
|
||||||
|
|
||||||
override fun handleMessage(msg: Message) {
|
|
||||||
val service: MusicService? = service.get()
|
|
||||||
if (msg.what == SAVE_QUEUES) {
|
|
||||||
service?.saveQueuesImpl()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue