playback: improve mediasession reliability

Fix some issues with PlaybackSessionConnector that resulted in the
position being stuck when a new song was played, alongside simplifying
the connector code to an extent.
This commit is contained in:
OxygenCobalt 2021-06-01 10:44:37 -06:00
parent ab28fb6323
commit 58eee7a891
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 27 additions and 36 deletions

View file

@ -91,8 +91,7 @@ dependencies {
// --- THIRD PARTY ---
// ExoPlayer
def exoplayer_version = "2.14.0"
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
implementation "com.google.android.exoplayer:exoplayer-core:2.14.0"
// Image loading
implementation "io.coil-kt:coil:1.2.1"

View file

@ -234,8 +234,8 @@ class PlaybackStateManager private constructor() {
private fun updatePlayback(song: Song, shouldPlay: Boolean = true) {
mIsInUserQueue = false
mSong = song
mPosition = 0
mSong = song
setPlaying(shouldPlay)
}

View file

@ -204,12 +204,6 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
playbackManager.next()
}
override fun onPositionDiscontinuity(reason: Int) {
if (reason == Player.DISCONTINUITY_REASON_SEEK) {
playbackManager.setPosition(player.currentPosition)
}
}
// --- PLAYBACK STATE CALLBACK OVERRIDES ---
override fun onSongUpdate(song: Song?) {

View file

@ -16,12 +16,7 @@ class PlaybackSessionConnector(
private val mediaSession: MediaSessionCompat
) : PlaybackStateManager.Callback, MediaSessionCompat.Callback() {
private val playbackManager = PlaybackStateManager.getInstance()
private val emptyMetadata = MediaMetadataCompat.Builder().build()
private val state = PlaybackStateCompat.Builder()
.setActions(ACTIONS)
private var playerState = PlaybackStateCompat.STATE_NONE
init {
mediaSession.setCallback(this)
@ -29,7 +24,6 @@ class PlaybackSessionConnector(
onSongUpdate(playbackManager.song)
onPlayingUpdate(playbackManager.isPlaying)
onPositionUpdate(playbackManager.position)
}
fun release() {
@ -55,11 +49,7 @@ class PlaybackSessionConnector(
}
override fun onSeekTo(position: Long) {
// Set the state to buffering to prevent weird delays on the duration counter when seeking.
// And yes, STATE_PAUSED is the only state that works with this code. Because of course it is.
setPlayerState(PlaybackStateCompat.STATE_PAUSED)
playbackManager.seekTo(position)
setPlayerState(getPlayerState())
}
override fun onRewind() {
@ -93,9 +83,10 @@ class PlaybackSessionConnector(
// --- PLAYBACKSTATEMANAGER CALLBACKS ---
override fun onSongUpdate(song: Song?) {
invalidateSessionState()
if (song == null) {
mediaSession.setMetadata(emptyMetadata)
setPlayerState(PlaybackStateCompat.STATE_STOPPED)
return
}
@ -116,24 +107,36 @@ class PlaybackSessionConnector(
}
override fun onPlayingUpdate(isPlaying: Boolean) {
setPlayerState(
if (playbackManager.isPlaying) {
PlaybackStateCompat.STATE_PLAYING
} else {
PlaybackStateCompat.STATE_PAUSED
}
)
invalidateSessionState()
}
override fun onSeek(position: Long) {
updateState()
invalidateSessionState()
}
// --- MISC ---
private fun setPlayerState(state: Int) {
playerState = state
updateState()
private fun invalidateSessionState() {
// Position updates arrive faster when you upload STATE_PAUSED for some inane reason.
val state = PlaybackStateCompat.Builder()
.setActions(ACTIONS)
.setState(
PlaybackStateCompat.STATE_PAUSED,
playbackManager.position,
1.0f,
SystemClock.elapsedRealtime()
)
mediaSession.setPlaybackState(state.build())
state.setState(
getPlayerState(),
playbackManager.position,
1.0f,
SystemClock.elapsedRealtime()
)
mediaSession.setPlaybackState(state.build())
}
private fun getPlayerState(): Int {
@ -148,11 +151,6 @@ class PlaybackSessionConnector(
}
}
private fun updateState() {
state.setState(playerState, playbackManager.position, 1.0f, SystemClock.elapsedRealtime())
mediaSession.setPlaybackState(state.build())
}
companion object {
const val ACTIONS = PlaybackStateCompat.ACTION_PLAY or
PlaybackStateCompat.ACTION_PAUSE or