android: let other apps browse the library and see the queue, behind a setting - #9
Merged
Merged
Conversation
…yService) PlaybackService is now a Media3 MediaLibraryService. Android Auto (declared via automotive_app_desc.xml), Wear, Assistant and any MediaBrowser can browse the first server's library: Albums, Artists, Playlists and Genres, each album or playlist with its tracks, and each artist or genre with its albums, plus local search. Playing an item sends the command the UI would send. An album, artist, playlist or genre plays as that context (starting at the tapped track). Search results play through PlayTracks. Added items become PlayNext or PlayLater. Voice "play ..." requests resolve to the best match and honour EXTRA_MEDIA_FOCUS. The session player's playlist is now the core's queue: recent history, the current entry, playing next and upcoming. Controllers show it as the session queue. Picking an entry sends JumpToQueueItem, and moving or removing upcoming entries sends MoveQueueItem or RemoveQueueItems. Cover art reaches controllers through ArtworkProvider (content URIs). It serves only this app and the controllers the session accepted, and only read-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFy2RUWjfmXxF8wCXTm7HM
A new device-local core setting, media.externalControl, decides whether other apps (Android Auto, Wear, media browsers, automation apps) may connect to the media session to browse the library, see the queue and control playback. It is shown in Settings > Playback. While it is off, the session accepts only the system's own controls. These are this app, Media3's notification controller, and callers holding MEDIA_CONTENT_CONTROL (SystemUI, Bluetooth). Before API 28 the platform's anonymous legacy controller is also accepted, because it cannot be identified. Every browse, search, add and custom command is checked again, so turning the setting off also strips already-connected apps of their commands and revokes their artwork access. PlaybackService keeps a copy of the value (excluded from backups), so a controller that connects before the core's snapshot is judged by the last choice. Also fixes library browsing: onConnect granted DEFAULT_SESSION_COMMANDS, which leaves out the library commands, so browsers would have been refused. It now grants DEFAULT_SESSION_AND_LIBRARY_COMMANDS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BFy2RUWjfmXxF8wCXTm7HM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Other apps can now browse the library, see the queue and control playback, through Android's media browser API. Examples are Android Auto, Wear, Assistant and media browser apps. All of this is off until you turn on the new Allow control by other apps setting.
Library browsing (
MediaLibraryService)PlaybackServiceis now a Media3MediaLibraryService. The app declaresautomotive_app_desc.xml, so it shows up in Android Auto.LibraryBrowseranswers browse requests with core queries against the first server:MediaIds.kt) carry everything needed to play the item and are URL-encoded, so an id another app saved from an earlier connection still works.PlayTracks.PlayNextorPlayLater.EXTRA_MEDIA_FOCUS. An empty request resumes playback.Queue
QueueView: the last 25 history entries, the current track, playing next and upcoming. Auto's queue view, Wear and the legacysetQueueshow it.JumpToQueueItem.MoveQueueItem, and removing one sendsRemoveQueueItems. The current track is never removed.Artwork
ArtworkProviderserves cover art ascontent://<package>.artwork/<size>/<coverArt>, because other apps cannot read the core's cache files."Allow control by other apps" (
media.externalControl)MEDIA_CONTENT_CONTROL(SystemUI, Bluetooth, checked by uid).Testing
MediaIdsTest,LibraryBrowserTest(runs againstFakeCore),CoreSessionQueueTest,ExternalControlTest, plus new cases inManifestRulesTestandSettingsCategoriesTest../gradlew testDebugUnitTestpasses: app 125, core 77, playback 62 tests.cargo test -p hocket-core --lib settingspasses.:app:assembleDebugbuilds, and the merged manifest has the right provider authority.🤖 Generated with Claude Code
https://claude.ai/code/session_01BFy2RUWjfmXxF8wCXTm7HM
Generated by Claude Code