Fix persistence bugs with notification
Fix issues where the notification for Auxio will show up incomplete during the restore process.
This commit is contained in:
parent
27777bf352
commit
da224ffda0
6 changed files with 122 additions and 78 deletions
|
|
@ -12,7 +12,6 @@ import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.NavOptions
|
import androidx.navigation.NavOptions
|
||||||
import androidx.navigation.findNavController
|
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.ui.NavigationUI
|
import androidx.navigation.ui.NavigationUI
|
||||||
|
|
@ -50,8 +49,8 @@ class MainFragment : Fragment() {
|
||||||
getInactiveAlpha(accent.first)
|
getInactiveAlpha(accent.first)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Set up the tints for the navigation icon
|
// Set up the tints for the navigation icons + text
|
||||||
val navIconTints = ColorStateList(
|
val navTints = ColorStateList(
|
||||||
arrayOf(
|
arrayOf(
|
||||||
intArrayOf(-android.R.attr.state_checked),
|
intArrayOf(-android.R.attr.state_checked),
|
||||||
intArrayOf(android.R.attr.state_checked)
|
intArrayOf(android.R.attr.state_checked)
|
||||||
|
|
@ -68,8 +67,8 @@ class MainFragment : Fragment() {
|
||||||
|
|
||||||
binding.lifecycleOwner = this
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
binding.navBar.itemIconTintList = navIconTints
|
binding.navBar.itemIconTintList = navTints
|
||||||
binding.navBar.itemTextColor = navIconTints
|
binding.navBar.itemTextColor = navTints
|
||||||
|
|
||||||
navController?.let {
|
navController?.let {
|
||||||
binding.navBar.setOnNavigationItemSelectedListener { item ->
|
binding.navBar.setOnNavigationItemSelectedListener { item ->
|
||||||
|
|
@ -93,6 +92,8 @@ class MainFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playbackModel.restorePlaybackIfNeeded(requireContext())
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "Fragment Created.")
|
Log.d(this::class.simpleName, "Fragment Created.")
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,27 @@ import android.net.Uri
|
||||||
|
|
||||||
// --- MUSIC MODELS ---
|
// --- MUSIC MODELS ---
|
||||||
|
|
||||||
// The base model for all music
|
/**
|
||||||
// This is used in a lot of general functions in order to have generic utilities
|
* The base data object for all music.
|
||||||
|
* @property id The ID that is assigned to this object
|
||||||
|
* @property name The name of this object (Such as a song title)
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
sealed class BaseModel {
|
sealed class BaseModel {
|
||||||
abstract val id: Long
|
abstract val id: Long
|
||||||
abstract val name: String
|
abstract val name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
// Song
|
/**
|
||||||
|
* The data object for a song. Inherits [BaseModel].
|
||||||
|
* @property albumId The Song's Album ID. Never use this outside of when attaching a song to its album.
|
||||||
|
* @property track The Song's Track number
|
||||||
|
* @property duration The duration of the song, in millis.
|
||||||
|
* @property album The Song's parent album. Use this instead of [albumId].
|
||||||
|
* @property seconds The Song's duration in seconds
|
||||||
|
* @property formattedDuration The Song's duration as a duration string.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
data class Song(
|
data class Song(
|
||||||
override val id: Long = -1,
|
override val id: Long = -1,
|
||||||
override var name: String,
|
override var name: String,
|
||||||
|
|
@ -25,7 +38,17 @@ data class Song(
|
||||||
val formattedDuration: String = seconds.toDuration()
|
val formattedDuration: String = seconds.toDuration()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Album
|
/**
|
||||||
|
* The data object for an album. Inherits [BaseModel].
|
||||||
|
* @property artistId The Album's parent artist ID. Do not use this outside of attaching an album to its parent artist.
|
||||||
|
* @property coverUri The [Uri] for the album's cover. **Load this using Coil.**
|
||||||
|
* @property year The year this album was released. 0 if there is none in the metadata.
|
||||||
|
* @property artist The Album's parent [Artist]. use this instead of [artistId]
|
||||||
|
* @property songs The Album's child [Song]s.
|
||||||
|
* @property numSongs The amount of songs in an Album.
|
||||||
|
* @property totalDuration The combined duration of all of the album's child songs, formatted.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
data class Album(
|
data class Album(
|
||||||
override val id: Long = -1,
|
override val id: Long = -1,
|
||||||
override val name: String,
|
override val name: String,
|
||||||
|
|
@ -46,7 +69,10 @@ data class Album(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Artist
|
/**
|
||||||
|
* The data object for an artist. Inherits [BaseModel]
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
data class Artist(
|
data class Artist(
|
||||||
override val id: Long = -1,
|
override val id: Long = -1,
|
||||||
override var name: String
|
override var name: String
|
||||||
|
|
@ -71,7 +97,12 @@ data class Artist(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Genre
|
/**
|
||||||
|
* The data object for a genre. Inherits [BaseModel]
|
||||||
|
* @property artists The list of all [Artist]s in this genre
|
||||||
|
* @property songs The list of all [Song]s in this genre.
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
data class Genre(
|
data class Genre(
|
||||||
override val id: Long = -1,
|
override val id: Long = -1,
|
||||||
override var name: String,
|
override var name: String,
|
||||||
|
|
@ -102,7 +133,9 @@ data class Genre(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header [Used for search, nothing else]
|
/**
|
||||||
|
* A data object used solely for the "Header" UI element. Inherits [BaseModel].
|
||||||
|
*/
|
||||||
data class Header(
|
data class Header(
|
||||||
override val id: Long = -1,
|
override val id: Long = -1,
|
||||||
override var name: String = "",
|
override var name: String = "",
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ import org.oxycblt.auxio.playback.state.PlaybackMode
|
||||||
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
import org.oxycblt.auxio.playback.state.PlaybackStateManager
|
||||||
|
|
||||||
object NotificationUtils {
|
object NotificationUtils {
|
||||||
val DO_COMPAT_SUBTEXT = Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
|
||||||
|
|
||||||
const val CHANNEL_ID = "CHANNEL_AUXIO_PLAYBACK"
|
const val CHANNEL_ID = "CHANNEL_AUXIO_PLAYBACK"
|
||||||
const val NOTIFICATION_ID = 0xA0A0
|
const val NOTIFICATION_ID = 0xA0A0
|
||||||
const val REQUEST_CODE = 0xA0C0
|
const val REQUEST_CODE = 0xA0C0
|
||||||
|
|
@ -81,6 +79,13 @@ fun NotificationManager.createMediaNotification(
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current metadata of a media notification.
|
||||||
|
* @param song The [Song] that the notification should reflect
|
||||||
|
* @param context The [Context] needed to load the cover bitmap
|
||||||
|
* @param onDone A callback for when the process is finished
|
||||||
|
* @author OxygenCobalt
|
||||||
|
*/
|
||||||
fun NotificationCompat.Builder.setMetadata(song: Song, context: Context, onDone: () -> Unit) {
|
fun NotificationCompat.Builder.setMetadata(song: Song, context: Context, onDone: () -> Unit) {
|
||||||
setContentTitle(song.name)
|
setContentTitle(song.name)
|
||||||
setContentText(
|
setContentText(
|
||||||
|
|
@ -89,7 +94,7 @@ fun NotificationCompat.Builder.setMetadata(song: Song, context: Context, onDone:
|
||||||
|
|
||||||
// On older versions of android [API <26], show the song's album on the subtext instead of
|
// On older versions of android [API <26], show the song's album on the subtext instead of
|
||||||
// the current mode, as that makes more sense for the old style of media notifications.
|
// the current mode, as that makes more sense for the old style of media notifications.
|
||||||
if (NotificationUtils.DO_COMPAT_SUBTEXT) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||||
setSubText(song.album.name)
|
setSubText(song.album.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,7 +107,7 @@ fun NotificationCompat.Builder.setMetadata(song: Song, context: Context, onDone:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// I have no idea how to update actions on the fly so I have to use these restricted APIs.
|
// I have no idea how to update a specific action on the fly so I have to use these restricted APIs
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
fun NotificationCompat.Builder.updatePlaying(context: Context) {
|
fun NotificationCompat.Builder.updatePlaying(context: Context) {
|
||||||
mActions[2] = newAction(NotificationUtils.ACTION_PLAY_PAUSE, context)
|
mActions[2] = newAction(NotificationUtils.ACTION_PLAY_PAUSE, context)
|
||||||
|
|
@ -114,7 +119,7 @@ fun NotificationCompat.Builder.updateLoop(context: Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun NotificationCompat.Builder.updateMode(context: Context) {
|
fun NotificationCompat.Builder.updateMode(context: Context) {
|
||||||
if (!NotificationUtils.DO_COMPAT_SUBTEXT) {
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
|
||||||
val playbackManager = PlaybackStateManager.getInstance()
|
val playbackManager = PlaybackStateManager.getInstance()
|
||||||
|
|
||||||
// If playing from all songs, set the subtext as that, otherwise the currently played parent.
|
// If playing from all songs, set the subtext as that, otherwise the currently played parent.
|
||||||
|
|
@ -126,6 +131,11 @@ fun NotificationCompat.Builder.updateMode(context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new [NotificationCompat.Action].
|
||||||
|
* @param action The action that the notification action should represent
|
||||||
|
* @param context The [Context] needed to create the action
|
||||||
|
*/
|
||||||
private fun newAction(action: String, context: Context): NotificationCompat.Action {
|
private fun newAction(action: String, context: Context): NotificationCompat.Action {
|
||||||
val playbackManager = PlaybackStateManager.getInstance()
|
val playbackManager = PlaybackStateManager.getInstance()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,19 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
|
|
||||||
if (playbackManager.song != null) {
|
if (playbackManager.song != null) {
|
||||||
restorePlayer()
|
restorePlayer()
|
||||||
|
notification.updateLoop(this)
|
||||||
|
notification.updateMode(this)
|
||||||
|
notification.updatePlaying(this)
|
||||||
|
|
||||||
|
playbackManager.song?.let {
|
||||||
|
notification.setMetadata(it, this) {
|
||||||
|
if (playbackManager.isPlaying) {
|
||||||
|
startForegroundOrNotify("Restore")
|
||||||
|
} else {
|
||||||
|
stopForegroundAndNotification()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,8 +236,13 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadMetadataToSession(it)
|
uploadMetadataToSession(it)
|
||||||
notification.setMetadata(playbackManager.song!!, this) {
|
|
||||||
startForegroundOrNotify()
|
if (playbackManager.isRestored) {
|
||||||
|
notification.setMetadata(playbackManager.song!!, this) {
|
||||||
|
startForegroundOrNotify("Song")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notification.setMetadata(playbackManager.song!!, this) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
@ -238,7 +256,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
override fun onModeUpdate(mode: PlaybackMode) {
|
override fun onModeUpdate(mode: PlaybackMode) {
|
||||||
notification.updateMode(this)
|
notification.updateMode(this)
|
||||||
|
|
||||||
startForegroundOrNotify()
|
startForegroundOrNotify("Mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayingUpdate(isPlaying: Boolean) {
|
override fun onPlayingUpdate(isPlaying: Boolean) {
|
||||||
|
|
@ -247,13 +265,13 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
if (isPlaying && !player.isPlaying) {
|
if (isPlaying && !player.isPlaying) {
|
||||||
player.play()
|
player.play()
|
||||||
notification.updatePlaying(this)
|
notification.updatePlaying(this)
|
||||||
startForegroundOrNotify()
|
startForegroundOrNotify("Play")
|
||||||
|
|
||||||
startPollingPosition()
|
startPollingPosition()
|
||||||
} else {
|
} else {
|
||||||
player.pause()
|
player.pause()
|
||||||
notification.updatePlaying(this)
|
notification.updatePlaying(this)
|
||||||
startForegroundOrNotify()
|
startForegroundOrNotify("Pause")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,7 +288,7 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.updateLoop(this)
|
notification.updateLoop(this)
|
||||||
startForegroundOrNotify()
|
startForegroundOrNotify("Loop")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSeekConfirm(position: Long) {
|
override fun onSeekConfirm(position: Long) {
|
||||||
|
|
@ -279,20 +297,6 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
player.seekTo(position)
|
player.seekTo(position)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNeedContextToRestoreState() {
|
|
||||||
Log.d(this::class.simpleName, "Giving context to PlaybackStateManager")
|
|
||||||
|
|
||||||
serviceScope.launch {
|
|
||||||
playbackManager.getStateFromDatabase(this@PlaybackService)
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "notification restore")
|
|
||||||
|
|
||||||
// FIXME: Current position just will not show on notification when state is restored
|
|
||||||
restorePlayer()
|
|
||||||
restoreNotification()
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- OTHER FUNCTIONS ---
|
// --- OTHER FUNCTIONS ---
|
||||||
|
|
||||||
private fun restorePlayer() {
|
private fun restorePlayer() {
|
||||||
|
|
@ -301,27 +305,13 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
player.setMediaItem(item)
|
player.setMediaItem(item)
|
||||||
player.prepare()
|
player.prepare()
|
||||||
player.seekTo(playbackManager.position)
|
player.seekTo(playbackManager.position)
|
||||||
|
|
||||||
notification.setMetadata(it, this) {
|
|
||||||
startForegroundOrNotify()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun restoreNotification() {
|
override fun onRestoreFinish() {
|
||||||
playbackManager.song?.let {
|
Log.d(this::class.simpleName, "Restore done")
|
||||||
uploadMetadataToSession(it)
|
|
||||||
notification.updateLoop(this)
|
|
||||||
notification.updateMode(this)
|
|
||||||
notification.updatePlaying(this)
|
|
||||||
notification.setMetadata(it, this) {
|
|
||||||
startForegroundOrNotify()
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
restorePlayer()
|
||||||
}
|
|
||||||
|
|
||||||
stopForegroundAndNotification()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun uploadMetadataToSession(song: Song) {
|
private fun uploadMetadataToSession(song: Song) {
|
||||||
|
|
@ -356,19 +346,23 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startForegroundOrNotify() {
|
private fun startForegroundOrNotify(reason: String) {
|
||||||
// Start the service in the foreground if haven't already.
|
// Start the service in the foreground if haven't already.
|
||||||
if (!isForeground) {
|
if (playbackManager.isRestored) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
Log.d(this::class.simpleName, "Starting foreground because of $reason")
|
||||||
startForeground(
|
|
||||||
NotificationUtils.NOTIFICATION_ID, notification.build(),
|
if (!isForeground) {
|
||||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
)
|
startForeground(
|
||||||
|
NotificationUtils.NOTIFICATION_ID, notification.build(),
|
||||||
|
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
startForeground(NotificationUtils.NOTIFICATION_ID, notification.build())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
startForeground(NotificationUtils.NOTIFICATION_ID, notification.build())
|
notificationManager.notify(NotificationUtils.NOTIFICATION_ID, notification.build())
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
notificationManager.notify(NotificationUtils.NOTIFICATION_ID, notification.build())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
package org.oxycblt.auxio.playback
|
package org.oxycblt.auxio.playback
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.Transformations
|
import androidx.lifecycle.Transformations
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.oxycblt.auxio.music.Album
|
import org.oxycblt.auxio.music.Album
|
||||||
import org.oxycblt.auxio.music.Artist
|
import org.oxycblt.auxio.music.Artist
|
||||||
import org.oxycblt.auxio.music.BaseModel
|
import org.oxycblt.auxio.music.BaseModel
|
||||||
|
|
@ -78,14 +81,10 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
||||||
|
|
||||||
// If the PlaybackViewModel was cleared [Signified by PlaybackStateManager still being
|
// If the PlaybackViewModel was cleared [Signified by PlaybackStateManager still being
|
||||||
// around & the fact that we are in the init function], then attempt to restore the
|
// around & the fact that we are in the init function], then attempt to restore the
|
||||||
// viewmodel state.
|
// viewmodel state. If it isn't, then wait for MainFragment to give the command to restore
|
||||||
|
// PlaybackStateManager.
|
||||||
if (playbackManager.isRestored) {
|
if (playbackManager.isRestored) {
|
||||||
restorePlaybackState()
|
restorePlaybackState()
|
||||||
} else {
|
|
||||||
// If [PlaybackStateManger] was also cleared [Due to Auxio's process dying], then
|
|
||||||
// attempt to restore it [Albeit PlaybackService will need to do the job as it
|
|
||||||
// has a context while PlaybackViewModel doesn't].
|
|
||||||
playbackManager.needContextToRestoreState()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,6 +248,14 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
|
||||||
mIsSeeking.value = value
|
mIsSeeking.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun restorePlaybackIfNeeded(context: Context) {
|
||||||
|
if (!playbackManager.isRestored) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
playbackManager.getStateFromDatabase(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --- OVERRIDES ---
|
// --- OVERRIDES ---
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import kotlin.random.Random
|
||||||
*
|
*
|
||||||
* All instantiation should be done with [PlaybackStateManager.from()].
|
* All instantiation should be done with [PlaybackStateManager.from()].
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
* FIXME: Add started variable instead of relying on mSong being null
|
|
||||||
*/
|
*/
|
||||||
class PlaybackStateManager private constructor() {
|
class PlaybackStateManager private constructor() {
|
||||||
// Playback
|
// Playback
|
||||||
|
|
@ -455,10 +454,6 @@ class PlaybackStateManager private constructor() {
|
||||||
// TODO: Persist queue edits?
|
// TODO: Persist queue edits?
|
||||||
// FIXME: Shuffling w/o knowing the original queue edit from keepSong will cause issues
|
// FIXME: Shuffling w/o knowing the original queue edit from keepSong will cause issues
|
||||||
|
|
||||||
fun needContextToRestoreState() {
|
|
||||||
callbacks.forEach { it.onNeedContextToRestoreState() }
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun saveStateToDatabase(context: Context) {
|
suspend fun saveStateToDatabase(context: Context) {
|
||||||
Log.d(this::class.simpleName, "Saving state to DB.")
|
Log.d(this::class.simpleName, "Saving state to DB.")
|
||||||
|
|
||||||
|
|
@ -483,16 +478,19 @@ class PlaybackStateManager private constructor() {
|
||||||
return@withContext states
|
return@withContext states
|
||||||
}
|
}
|
||||||
|
|
||||||
mIsRestored = true
|
|
||||||
|
|
||||||
if (states.isEmpty()) {
|
if (states.isEmpty()) {
|
||||||
Log.d(this::class.simpleName, "Nothing here. Not restoring.")
|
Log.d(this::class.simpleName, "Nothing here. Not restoring.")
|
||||||
|
|
||||||
|
mIsRestored = true
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(this::class.simpleName, "Old state found, ${states[0]}")
|
Log.d(this::class.simpleName, "Old state found, ${states[0]}")
|
||||||
|
|
||||||
unpackFromPlaybackState(states[0])
|
unpackFromPlaybackState(states[0])
|
||||||
|
|
||||||
|
mIsRestored = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun packToPlaybackState(): PlaybackState {
|
private fun packToPlaybackState(): PlaybackState {
|
||||||
|
|
@ -580,6 +578,7 @@ class PlaybackStateManager private constructor() {
|
||||||
callbacks.forEach {
|
callbacks.forEach {
|
||||||
it.onSeekConfirm(mPosition)
|
it.onSeekConfirm(mPosition)
|
||||||
it.onModeUpdate(mMode)
|
it.onModeUpdate(mMode)
|
||||||
|
it.onRestoreFinish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -600,7 +599,7 @@ class PlaybackStateManager private constructor() {
|
||||||
fun onShuffleUpdate(isShuffling: Boolean) {}
|
fun onShuffleUpdate(isShuffling: Boolean) {}
|
||||||
fun onLoopUpdate(mode: LoopMode) {}
|
fun onLoopUpdate(mode: LoopMode) {}
|
||||||
fun onSeekConfirm(position: Long) {}
|
fun onSeekConfirm(position: Long) {}
|
||||||
fun onNeedContextToRestoreState() {}
|
fun onRestoreFinish() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue