diff --git a/CHANGELOG.md b/CHANGELOG.md index 738d9a66e..6e0959980 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ at the cost of longer loading times - Added basic awareness of multi-value vorbis tags [#197, dependent on this feature] - Added Last Added sorting - Search now takes sort tags and file names in account [#184] +- Added option to clear playback state in settings #### What's Fixed - Fixed default material theme being used before app shows up diff --git a/app/build.gradle b/app/build.gradle index 47ec4e6a9..085023ee3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -94,7 +94,7 @@ dependencies { // Exoplayer // WARNING: THE EXOPLAYER VERSION MUST BE KEPT IN LOCK-STEP WITH THE PRE-BUILD SCRIPT. // IF NOT, VERY UNFRIENDLY BUILD FAILURES AND CRASHES MAY ENSUE. - implementation "com.google.android.exoplayer:exoplayer-core:2.18.0" + implementation "com.google.android.exoplayer:exoplayer-core:2.18.1" implementation fileTree(dir: "libs", include: ["extension-*.aar"]) // Image loading diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fc9b42d46..c5c15cb01 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,6 +24,7 @@ android:supportsRtl="true" android:theme="@style/Theme.Auxio.App" android:dataExtractionRules="@xml/data_extraction_rules" + android:appCategory="audio" tools:ignore="UnusedAttribute"> , parent: MusicParent?) { - updateMediaMetadata(playbackManager.song, parent) - } - override fun onIndexMoved(index: Int) { updateMediaMetadata(playbackManager.song, playbackManager.parent) + invalidateSessionState() + } + + override fun onQueueChanged(index: Int, queue: List) { + updateQueue(queue) + } + + override fun onNewPlayback(index: Int, queue: List, parent: MusicParent?) { + updateMediaMetadata(playbackManager.song, parent) + updateQueue(queue) + invalidateSessionState() } private fun updateMediaMetadata(song: Song?, parent: MusicParent?) { if (song == null) { mediaSession.setMetadata(emptyMetadata) - callback.onPostNotification(null) + callback.onPostNotification(null, "song update") return } @@ -163,11 +172,29 @@ class MediaSessionComponent( val metadata = builder.build() mediaSession.setMetadata(metadata) notification.updateMetadata(metadata) - callback.onPostNotification(notification) + callback.onPostNotification(notification, "song update") } }) } + private fun updateQueue(queue: List) { + val queueItems = + queue.mapIndexed { i, song -> + val description = + MediaDescriptionCompat.Builder() + .setMediaId(song.id.toString()) + .setTitle(song.resolveName(context)) + .setSubtitle(song.resolveIndividualArtistName(context)) + .setIconUri(song.album.coverUri) // Use lower-quality covers for speed + .setMediaUri(song.uri) + .build() + + MediaSessionCompat.QueueItem(description, i.toLong()) + } + + mediaSession.setQueue(queueItems) + } + override fun onPlayingChanged(isPlaying: Boolean) { invalidateSessionState() invalidateNotificationActions() @@ -274,12 +301,7 @@ class MediaSessionComponent( private fun invalidateSessionState() { logD("Updating media session playback state") - // There are two unfixable issues with this code: - // 1. If the position is changed while paused (from the app), the position just won't - // update unless I re-post the notification. However, I cannot do such without being - // rate-limited. I cannot believe android rate-limits media notifications when they - // have to be updated as often as they need to. - // 2. Due to metadata updates being delayed but playback remaining ongoing, the position + // Note: Due to metadata updates being delayed but playback remaining ongoing, the position // will be wonky until we can upload a duration. Again, this ties back to how I must // aggressively batch notification updates to prevent rate-limiting. // Android 13 seems to resolve these, but I'm still stuck with these issues below that @@ -288,13 +310,8 @@ class MediaSessionComponent( val state = PlaybackStateCompat.Builder() .setActions(ACTIONS) - .addCustomAction( - PlaybackStateCompat.CustomAction.Builder( - PlaybackService.ACTION_INC_REPEAT_MODE, - context.getString(R.string.desc_change_repeat), - R.drawable.ic_repeat_off_24) - .build()) .setBufferedPosition(player.bufferedPosition) + .setActiveQueueItemId(playbackManager.index.toLong()) val playerState = if (playbackManager.isPlaying) { @@ -318,7 +335,7 @@ class MediaSessionComponent( } if (!provider.isBusy) { - callback.onPostNotification(notification) + callback.onPostNotification(notification, "new notification actions") } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt index 7284c893f..4418e5ab9 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/PlaybackService.kt @@ -271,7 +271,7 @@ class PlaybackService : player.playWhenReady = isPlaying } - override fun onPostNotification(notification: NotificationComponent?) { + override fun onPostNotification(notification: NotificationComponent?, reason: String) { if (notification == null) { // This case is only here if I ever need to move foreground stopping from // the player code to the notification code. @@ -280,7 +280,7 @@ class PlaybackService : } if (hasPlayed) { - logD("Updating notification") + logD("Updating notification [Reason: $reason]") if (!foregroundManager.tryStartForeground(notification)) { notification.post() } diff --git a/prebuild.py b/prebuild.py index f5c4e418d..659718017 100755 --- a/prebuild.py +++ b/prebuild.py @@ -19,7 +19,7 @@ import re # WARNING: THE EXOPLAYER VERSION MUST BE KEPT IN LOCK-STEP WITH THE FLAC EXTENSION AND # THE GRADLE DEPENDENCY. IF NOT, VERY UNFRIENDLY BUILD FAILURES AND CRASHES MAY ENSUE. -EXO_VERSION = "2.18.0" +EXO_VERSION = "2.18.1" FLAC_VERSION = "1.3.2" FATAL="\033[1;31m"