Opening a media app that can't connect no longer drops the music you were listening to

This commit is contained in:
Seb3thehacker committed 2026-11-06 12:04:28 -08:00
1 parent 6ec0325f7d
commit cec98fcde6
2 files changed
+16 -4

No files matched your search

@@ -37,7 +37,13 @@ object CarServices {
private const val REPAUSE_MS = 2_000L
val nav: CarAppConnection by lazy { CarAppConnection(requireNotNull(context)) }
val media: CarMedia by lazy { CarMedia(requireNotNull(context)) }
val media: CarMedia by lazy {
CarMedia(requireNotNull(context)).also { m ->
// Remembered only once it connects: an app that refuses (NewPipe without Notification
// access) must not replace the one the driver was listening to on the next drive.
m.onReady = { app -> CarSettings.setLastMedia(app.component.flattenToString()) }
}
}
/** [nav], or null before the car screen has set things up. */
fun navOrNull(): CarAppConnection? = if (context != null) nav else null
@@ -67,7 +73,7 @@ object CarServices {
private var autoplayPending = false
/**
* The app that was playing when the driver opened another one. Opening an app is only a look
* The app that was playing, or paused with a track loaded, when the driver opened another one. Opening an app is only a look
* at its library: until something plays there, the music carries on in this one, so leaving
* the new app's screen goes back to it, as Android Auto does.
*/
@@ -138,13 +144,14 @@ object CarServices {
// --- media ---------------------------------------------------------------------------
fun openMedia(app: MediaApp, autoplay: Boolean = false) {
CarSettings.setLastMedia(app.component.flattenToString())
val phase = media.phase.value
val live = phase == CarMedia.Phase.READY || phase == CarMedia.Phase.CONNECTING
if (_mediaApp.value?.component == app.component && live) return
val previous = _mediaApp.value
stillPlaying = previous?.takeIf { it.component != app.component && media.now.value.playing && !autoplay }
// Paused counts too: a track loaded there is still the music the driver is listening to.
val loaded = media.now.value.let { it.playing || it.title.isNotEmpty() }
stillPlaying = previous?.takeIf { it.component != app.component && loaded && !autoplay }
_mediaApp.value = app
autoplayPending = autoplay
media.connect(app)
@@ -188,6 +188,9 @@ class CarMedia(private val context: Context) {
/** The music app Gearslip is attached to, for the assistant to name; null when there's none. */
val appLabel: String? get() = connecting?.label?.takeIf { controller != null }
/** Called once an app is connected and can be played, library or not. */
var onReady: ((MediaApp) -> Unit)? = null
private val _phase = MutableStateFlow(Phase.IDLE)
val phase: StateFlow<Phase> = _phase.asStateFlow()
@@ -354,6 +357,7 @@ class CarMedia(private val context: Context) {
attach(session)
_browse.value = BrowseState(loading = false, unavailable = true)
_phase.value = Phase.READY
onReady?.invoke(app)
}
private fun onConnected(app: MediaApp) {
@@ -366,6 +370,7 @@ class CarMedia(private val context: Context) {
mb.extras?.let { childStyles[mb.root] = it.getInt(STYLE_BROWSABLE, 0) to it.getInt(STYLE_PLAYABLE, 0) }
path.clear()
_phase.value = Phase.READY
onReady?.invoke(app)
open(mb.root)
}