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 --- // --- THIRD PARTY ---
// ExoPlayer // ExoPlayer
def exoplayer_version = "2.14.0" implementation "com.google.android.exoplayer:exoplayer-core:2.14.0"
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
// Image loading // Image loading
implementation "io.coil-kt:coil:1.2.1" 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) { private fun updatePlayback(song: Song, shouldPlay: Boolean = true) {
mIsInUserQueue = false mIsInUserQueue = false
mSong = song
mPosition = 0 mPosition = 0
mSong = song
setPlaying(shouldPlay) setPlaying(shouldPlay)
} }

View file

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

View file

@ -16,12 +16,7 @@ class PlaybackSessionConnector(
private val mediaSession: MediaSessionCompat private val mediaSession: MediaSessionCompat
) : PlaybackStateManager.Callback, MediaSessionCompat.Callback() { ) : PlaybackStateManager.Callback, MediaSessionCompat.Callback() {
private val playbackManager = PlaybackStateManager.getInstance() private val playbackManager = PlaybackStateManager.getInstance()
private val emptyMetadata = MediaMetadataCompat.Builder().build() private val emptyMetadata = MediaMetadataCompat.Builder().build()
private val state = PlaybackStateCompat.Builder()
.setActions(ACTIONS)
private var playerState = PlaybackStateCompat.STATE_NONE
init { init {
mediaSession.setCallback(this) mediaSession.setCallback(this)
@ -29,7 +24,6 @@ class PlaybackSessionConnector(
onSongUpdate(playbackManager.song) onSongUpdate(playbackManager.song)
onPlayingUpdate(playbackManager.isPlaying) onPlayingUpdate(playbackManager.isPlaying)
onPositionUpdate(playbackManager.position)
} }
fun release() { fun release() {
@ -55,11 +49,7 @@ class PlaybackSessionConnector(
} }
override fun onSeekTo(position: Long) { 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) playbackManager.seekTo(position)
setPlayerState(getPlayerState())
} }
override fun onRewind() { override fun onRewind() {
@ -93,9 +83,10 @@ class PlaybackSessionConnector(
// --- PLAYBACKSTATEMANAGER CALLBACKS --- // --- PLAYBACKSTATEMANAGER CALLBACKS ---
override fun onSongUpdate(song: Song?) { override fun onSongUpdate(song: Song?) {
invalidateSessionState()
if (song == null) { if (song == null) {
mediaSession.setMetadata(emptyMetadata) mediaSession.setMetadata(emptyMetadata)
setPlayerState(PlaybackStateCompat.STATE_STOPPED)
return return
} }
@ -116,24 +107,36 @@ class PlaybackSessionConnector(
} }
override fun onPlayingUpdate(isPlaying: Boolean) { override fun onPlayingUpdate(isPlaying: Boolean) {
setPlayerState( invalidateSessionState()
if (playbackManager.isPlaying) {
PlaybackStateCompat.STATE_PLAYING
} else {
PlaybackStateCompat.STATE_PAUSED
}
)
} }
override fun onSeek(position: Long) { override fun onSeek(position: Long) {
updateState() invalidateSessionState()
} }
// --- MISC --- // --- MISC ---
private fun setPlayerState(state: Int) { private fun invalidateSessionState() {
playerState = state // Position updates arrive faster when you upload STATE_PAUSED for some inane reason.
updateState() 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 { 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 { companion object {
const val ACTIONS = PlaybackStateCompat.ACTION_PLAY or const val ACTIONS = PlaybackStateCompat.ACTION_PLAY or
PlaybackStateCompat.ACTION_PAUSE or PlaybackStateCompat.ACTION_PAUSE or