Migrate Android Auto support to audio_service#223
Conversation
📝 WalkthroughWalkthroughAndroid Auto integration is migrated from custom ChangesAudio service Android Auto migration
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant AndroidAuto
participant MuslyAudioHandler
participant LibraryProvider
participant PlayerProvider
AndroidAuto->>MuslyAudioHandler: Browse or playback request
MuslyAudioHandler->>LibraryProvider: Request library data
LibraryProvider-->>MuslyAudioHandler: Return media items
MuslyAudioHandler->>PlayerProvider: Invoke playback callback
PlayerProvider-->>MuslyAudioHandler: Update playback or remote state
MuslyAudioHandler-->>AndroidAuto: Publish media-session state
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/providers/library_provider.dart`:
- Around line 474-479: Update the server-offline handling in the song, album,
artist, and playlist branches of the relevant provider method: assign each
downloaded-only filtered collection unconditionally, including empty results,
instead of preserving the full catalog. For playlists, retain only playlists
containing at least one downloaded song, using the existing downloaded ID set
and playlist song data.
In `@lib/providers/player_provider.dart`:
- Line 2755: Update _onCastStateChanged() to initialize setRemotePlayback’s
volume from CastService.mediaState.volume instead of the fixed 50, and keep the
Android Auto remote volume synchronized when subsequent Cast-side volume changes
are reported.
In `@lib/services/audio_handler.dart`:
- Around line 528-538: Update the AudioServiceConfig configuration to set
androidStopForegroundOnPause to false, keeping the audio service foregrounded
during pauses and preserving Android Auto cold-start/resume behavior. Do not add
battery-optimization handling or unrelated configuration changes.
- Around line 342-357: Update setRemotePlayback so the isRemote == false branch
emits a local PlaybackState after adding LocalAndroidPlaybackInfo, replacing the
remote playback state immediately; preserve the existing remote-mode update
behavior and construct the local state using the established playback-state
flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1ae1f6f8-f0f4-488b-a1f3-034764a64229
⛔ Files ignored due to path filters (2)
packages/flutter_chrome_cast/pubspec.lockis excluded by!**/*.lockpubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (16)
android/app/src/main/AndroidManifest.xmlandroid/app/src/main/kotlin/com/musly/musly/AndroidAutoPlugin.ktandroid/app/src/main/kotlin/com/musly/musly/AndroidSystemPlugin.ktandroid/app/src/main/kotlin/com/musly/musly/BluetoothMediaHelper.ktandroid/app/src/main/kotlin/com/musly/musly/LyricsPlugin.ktandroid/app/src/main/kotlin/com/musly/musly/MainActivity.ktandroid/app/src/main/kotlin/com/musly/musly/MusicService.ktlib/main.dartlib/providers/auth_provider.dartlib/providers/library_provider.dartlib/providers/player_provider.dartlib/services/android_auto_service.dartlib/services/android_system_service.dartlib/services/audio_handler.dartlib/services/services.dartpubspec.yaml
💤 Files with no reviewable changes (7)
- lib/services/services.dart
- android/app/src/main/kotlin/com/musly/musly/AndroidAutoPlugin.kt
- lib/services/android_auto_service.dart
- android/app/src/main/kotlin/com/musly/musly/MusicService.kt
- lib/services/android_system_service.dart
- android/app/src/main/kotlin/com/musly/musly/BluetoothMediaHelper.kt
- lib/providers/auth_provider.dart
Problem
Android Auto showed no recent items, no search, and playback couldn't be started from the car. Root cause: the custom MusicService (MediaBrowserServiceCompat) held no data of its own — it relied entirely on the Flutter engine being alive to push library data and answer search/playback requests over a MethodChannel/EventChannel bridge. When Android Auto starts the service directly (app never opened on the phone), MainActivity never runs, so the plugin's event sink stays null and every request from the car is silently dropped. On top of that, a callback registration bug (PlayerProvider was overwriting LibraryProvider's working onRequestLibraryData handler with a no-op) meant the browse tree could stay empty even with the app open.
Fix
Replaced the custom native MediaBrowserServiceCompat + MethodChannel bridge with audio_service, which already backed the iOS lock-screen integration. audio_service hosts its own MediaBrowserService and, when Android Auto connects with the app closed, spawns a headless Flutter engine and runs main() — so the browse tree, search, and playback commands are served by Dart code directly, with no dependency on the UI having been opened first.
Changes
Dart
Android (Kotlin)
Testing
Summary by CodeRabbit