Surface jukebox error message before falling back to local playback

This commit is contained in:
birdbird committed 2026-10-01 23:33:36 +02:00
1 parent 1ce70142a1
commit f3dd7808ac
2 files changed
+61 -8

No files matched your search

@@ -20,6 +20,7 @@ import android.os.Looper
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.TaskStackBuilder
import androidx.core.text.HtmlCompat
import androidx.media3.common.AudioAttributes
import androidx.media3.common.C
import androidx.media3.common.C.USAGE_MEDIA
@@ -556,7 +557,62 @@ class PlaybackService :
* Connectivity failures additionally trigger a background reachability probe; only a
* failed probe - never the playback error itself - switches the library to automatic
* offline mode.
* Surfaces the reason why Jukebox playback failed before [updateBackend] falls back to
* local playback. Jukebox errors carry a string resource as their error code (see
* [JukeboxMediaPlayer.onError]); those messages are shown in an error notification.
* Any other error is only logged.
*/
private fun notifyJukeboxError(error: PlaybackException) {
val messageRes = when (error.errorCode) {
R.string.download_jukebox_not_authorized,
R.string.download_jukebox_server_too_old,
R.string.download_jukebox_offline -> error.errorCode
else -> return
}
val notificationManagerCompat = NotificationManagerCompat.from(this@PlaybackService)
NotificationUtil.ensureNotificationChannel(
id = NOTIFICATION_CHANNEL_ID,
name = NOTIFICATION_CHANNEL_NAME,
notificationManager = notificationManagerCompat
)
// The Jukebox messages contain inline markup (e.g. <b>), render it for the notification
val message = HtmlCompat.fromHtml(
getString(messageRes),
HtmlCompat.FROM_HTML_MODE_LEGACY
)
val fallback = getString(R.string.jukebox_fallback_text)
val builder =
NotificationCompat.Builder(this@PlaybackService, NOTIFICATION_CHANNEL_ID)
.setContentIntent(createContentPendingIntent())
.setSmallIcon(R.drawable.media3_notification_small_icon)
.setContentTitle(getString(R.string.jukebox_error_title))
.setStyle(
NotificationCompat.BigTextStyle().bigText(
"$message\n\n$fallback"
)
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true)
NotificationUtil.postNotificationIfPermitted(
notificationManagerCompat,
JUKEBOX_ERROR_NOTIFICATION_ID,
builder.build()
)
}
private fun createContentPendingIntent(): PendingIntent =
TaskStackBuilder.create(this@PlaybackService).run {
addNextIntent(Intent(this@PlaybackService, NavigationActivity::class.java))
val immutableFlag = FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT
getPendingIntent(0, immutableFlag)!!
}
private fun recoverFromPlaybackError(error: PlaybackException) {
val connectivity = error.hasTransientConnectivityFailure()
if (!connectivity && !error.hasOfflineCause()) return
@@ -639,6 +695,7 @@ class PlaybackService :
Timber.w(error, "Playback error")
if (actualBackend == PlaybackBackend.JUKEBOX) {
mainHandler.post {
notifyJukeboxError(error)
updateBackend(PlaybackBackend.LOCAL, retainDownloadsOnly = false)
}
return
@@ -822,16 +879,9 @@ class PlaybackService :
name = NOTIFICATION_CHANNEL_NAME,
notificationManager = notificationManagerCompat
)
val pendingIntent =
TaskStackBuilder.create(this@PlaybackService).run {
addNextIntent(Intent(this@PlaybackService, NavigationActivity::class.java))
val immutableFlag = FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT
getPendingIntent(0, immutableFlag)
}
val builder =
NotificationCompat.Builder(this@PlaybackService, NOTIFICATION_CHANNEL_ID)
.setContentIntent(pendingIntent)
.setContentIntent(createContentPendingIntent())
.setSmallIcon(R.drawable.media3_notification_small_icon)
.setContentTitle(getString(R.string.foreground_exception_title))
.setStyle(
@@ -874,5 +924,6 @@ class PlaybackService :
const val COMMAND_ARGUMENT_FROM_START = "fromStart"
const val COMMAND_ARGUMENT_BACKEND = "backend"
private const val NOTIFICATION_ID = 3009
private const val JUKEBOX_ERROR_NOTIFICATION_ID = 3010
}
}
@@ -65,6 +65,8 @@
<string name="download.jukebox_offline">Remote control is not available in offline mode.</string>
<string name="download.jukebox_on">Turned on remote control. Music is played on server.</string>
<string name="download.jukebox_server_too_old">Remote control is not supported. Please upgrade your Subsonic server.</string>
<string name="jukebox_error_title">Jukebox playback failed</string>
<string name="jukebox_fallback_text">Switching to local playback on this device.</string>
<string name="download.menu_equalizer">Equalizer</string>
<string name="download.menu_jukebox_off">Jukebox Off</string>
<string name="download.menu_jukebox_on">Jukebox On</string>