playback: simplify playbacknotification

Simplify the PlaybackNotification code to not have to pass Context for
an argument when it could simply be a private variable. This is okay,
as PlaybackNotification only lives as long as PlaybackService does.
This commit is contained in:
OxygenCobalt 2021-08-03 10:50:09 -06:00
parent 49db7e0741
commit 2abc91674b
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 29 additions and 28 deletions

View file

@ -21,10 +21,9 @@ class AudioReactor(
context: Context,
private val player: SimpleExoPlayer
) : AudioManager.OnAudioFocusChangeListener {
private val audioManager = context.getSystemServiceSafe(AudioManager::class)
private val settingsManager = SettingsManager.getInstance()
private val playbackManager = PlaybackStateManager.getInstance()
private val settingsManager = SettingsManager.getInstance()
private val audioManager = context.getSystemServiceSafe(AudioManager::class)
private val request = AudioFocusRequestCompat.Builder(AudioManagerCompat.AUDIOFOCUS_GAIN)
.setWillPauseWhenDucked(true)

View file

@ -14,7 +14,7 @@ import org.oxycblt.auxio.coil.loadBitmap
import org.oxycblt.auxio.music.Parent
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.state.LoopMode
import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.settings.SettingsManager
import org.oxycblt.auxio.ui.newBroadcastIntent
import org.oxycblt.auxio.ui.newMainIntent
@ -25,9 +25,11 @@ import org.oxycblt.auxio.ui.newMainIntent
*/
@SuppressLint("RestrictedApi")
class PlaybackNotification private constructor(
context: Context,
private val context: Context,
mediaToken: MediaSessionCompat.Token
) : NotificationCompat.Builder(context, CHANNEL_ID), PlaybackStateManager.Callback {
) : NotificationCompat.Builder(context, CHANNEL_ID) {
val settingsManager = SettingsManager.getInstance()
init {
setSmallIcon(R.drawable.ic_song)
setCategory(NotificationCompat.CATEGORY_SERVICE)
@ -47,16 +49,19 @@ class PlaybackNotification private constructor(
.setMediaSession(mediaToken)
.setShowActionsInCompactView(1, 2, 3)
)
// Don't connect to PlaybackStateManager here. This is because it's possible for this
// notification to not be updated by PlaybackStateManager before PlaybackService pushes
// the notification, resulting in invalid metadata.
}
// --- STATE FUNCTIONS ---
/**
* Set the metadata of the notification using [song].
* @param colorize Whether to show the album art of [song] on the notification
* @param onDone What to do when the loading of the album art is finished
*/
fun setMetadata(context: Context, song: Song, colorize: Boolean, onDone: () -> Unit) {
fun setMetadata(song: Song, onDone: () -> Unit) {
setContentTitle(song.name)
setContentText(song.album.artist.name)
@ -66,7 +71,7 @@ class PlaybackNotification private constructor(
setSubText(song.album.name)
}
if (colorize) {
if (!settingsManager.colorizeNotif) {
// loadBitmap() is concurrent, so only call back to the object calling this function when
// the loading is over.
loadBitmap(context, song) { bitmap ->
@ -82,28 +87,28 @@ class PlaybackNotification private constructor(
/**
* Set the playing icon on the notification
*/
fun setPlaying(context: Context, isPlaying: Boolean) {
fun setPlaying(isPlaying: Boolean) {
mActions[2] = buildPlayPauseAction(context, isPlaying)
}
/**
* Update the first action to reflect the [loopMode] given.
*/
fun setLoop(context: Context, loopMode: LoopMode) {
fun setLoop(loopMode: LoopMode) {
mActions[0] = buildLoopAction(context, loopMode)
}
/**
* Update the first action to reflect whether the queue is shuffled or not
*/
fun setShuffle(context: Context, isShuffling: Boolean) {
fun setShuffle(isShuffling: Boolean) {
mActions[0] = buildShuffleAction(context, isShuffling)
}
/**
* Apply the current [parent] to the header of the notification.
*/
fun setParent(context: Context, parent: Parent?) {
fun setParent(parent: Parent?) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return
// A blank parent always means that the mode is ALL_SONGS

View file

@ -48,7 +48,6 @@ import org.oxycblt.auxio.widgets.WidgetController
/**
* A service that manages the system-side aspects of playback, such as:
* - The single [SimpleExoPlayer] instance.
* - The [MediaSessionCompat]
* - The Media Notification
* - Headset management
* - Widgets
@ -56,8 +55,6 @@ import org.oxycblt.auxio.widgets.WidgetController
* This service relies on [PlaybackStateManager.Callback] and [SettingsManager.Callback],
* so therefore there's no need to bind to it to deliver commands.
* @author OxygenCobalt
*
* TODO: Try to split up this god object somewhat, such as making the notification state-aware.
*/
class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callback, SettingsManager.Callback {
@ -246,7 +243,7 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
player.prepare()
notification.setMetadata(
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
song, ::startForegroundOrNotify
)
return
@ -258,7 +255,7 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
}
override fun onParentUpdate(parent: Parent?) {
notification.setParent(this, parent)
notification.setParent(parent)
startForegroundOrNotify()
}
@ -272,13 +269,13 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
player.pause()
}
notification.setPlaying(this, isPlaying)
notification.setPlaying(isPlaying)
startForegroundOrNotify()
}
override fun onLoopUpdate(loopMode: LoopMode) {
if (!settingsManager.useAltNotifAction) {
notification.setLoop(this, loopMode)
notification.setLoop(loopMode)
startForegroundOrNotify()
}
@ -286,7 +283,7 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
override fun onShuffleUpdate(isShuffling: Boolean) {
if (settingsManager.useAltNotifAction) {
notification.setShuffle(this, isShuffling)
notification.setShuffle(isShuffling)
startForegroundOrNotify()
}
@ -301,16 +298,16 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
override fun onColorizeNotifUpdate(doColorize: Boolean) {
playbackManager.song?.let { song ->
notification.setMetadata(
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
song, ::startForegroundOrNotify
)
}
}
override fun onNotifActionUpdate(useAltAction: Boolean) {
if (useAltAction) {
notification.setShuffle(this, playbackManager.isShuffling)
notification.setShuffle(playbackManager.isShuffling)
} else {
notification.setLoop(this, playbackManager.loopMode)
notification.setLoop(playbackManager.loopMode)
}
startForegroundOrNotify()
@ -321,7 +318,7 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
connector.onSongUpdate(song)
notification.setMetadata(
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
song, ::startForegroundOrNotify
)
}
}
@ -329,7 +326,7 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
override fun onQualityCoverUpdate(doQualityCovers: Boolean) {
playbackManager.song?.let { song ->
notification.setMetadata(
this, song, settingsManager.colorizeNotif, ::startForegroundOrNotify
song, ::startForegroundOrNotify
)
}
}

View file

@ -31,6 +31,8 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.logE
import kotlin.reflect.KClass
const val INTENT_REQUEST_CODE = 0xA0A0
// --- VIEW CONFIGURATION ---
/**
@ -154,8 +156,6 @@ fun Context.showToast(@StringRes str: Int) {
Toast.makeText(applicationContext, getString(str), Toast.LENGTH_SHORT).show()
}
const val INTENT_REQUEST_CODE = 0xA0A0
/**
* Create a broadcast [PendingIntent]
*/