feat: MVP of MediaSessionCompat Android 13+ integration

This commit is contained in:
2026-07-27 00:16:46 -04:00
parent 2cf02ddcea
commit 1029586c6d
12 changed files with 538 additions and 82 deletions
+28 -8
View File
@@ -34,16 +34,31 @@ A dedicated settings screen where the user can view every setting and reset it.
`PlayerViewModel`/`AppScreen`).
- Room to grow: password field, connection timeout, theme, keep-screen-on.
## [ ] 3. Cast-style volume control
## [x] 3. Cast-style volume + OS media integration
When the MPD server is playing, present the volume control as a **"casting"
style** remote-volume control — the way MALP (and Google Cast) do — making it
visually clear you're controlling the *server's* output, not the phone's.
Done — full MALP-style **OS integration**, not just in-app. Architecture:
- Functionally we already send `setvol` to the server (`MpdClient.setVolume`);
this is mostly a UX/affordance change: a cast icon, "Casting to <host>" label,
distinct styling for remote vs local volume.
- Reference behaviour: MALP.
- **`MpdConnectionManager`** (app-scoped, held by `MusicRemoteApplication`) now
owns the single `MpdClient`, so the connection survives Activity recreation and
runs while the service is up. `PlayerViewModel` is a thin delegate over it.
- **`PlaybackService`** — a `mediaPlayback` foreground service hosting a
`MediaSessionCompat`:
- **Cast-style volume**: `setPlaybackToRemote(VolumeProviderCompat)` (absolute,
0100). The OS routes hardware volume keys to the *server* volume
**system-wide, even when the app is backgrounded** (verified: 50→40 via
injected keys from the launcher), and shows the remote-volume UI. Replaced
the earlier in-app `onKeyDown` hack. Rapid presses accumulate via
`pendingVolume`.
- **Now-playing notification / QS / lock-screen** via a `MediaStyle`
notification bound to the session, with prev/play-pause/next actions
(`MediaButtonReceiver`) and metadata/position mirrored from the flows.
- Needs `POST_NOTIFICATIONS` (requested in `MainActivity`) +
`FOREGROUND_SERVICE[_MEDIA_PLAYBACK]`.
- In-app **`CastIndicator`** ("Controlling <host>") still shown above the slider.
Notes: verified on the FiiO via injected key events (a rotary volume knob may not
emit `VOLUME_UP/DOWN` — hardware-dependent). Album art in the notification/session
is pending item #5.
## [ ] 4. Library browse — albums
@@ -85,3 +100,8 @@ and falls back to the connect screen. MALP does not do this.
**auto-reconnect transparently** (re-open connections, re-issue `idle`, resync
state) and keep showing the player. Consider a keepalive ping and, for
backgrounded playback control, a foreground service / partial wakelock.
- PARTIALLY ADDRESSED by item #3: the `mediaPlayback` foreground service now
keeps the process/connection alive in the background, which should stop Doze /
wifi power-save from tearing the sockets down (the most likely cause). Still
worth verifying over a long idle, and adding transparent auto-reconnect +
keepalive ping as defense-in-depth (e.g. against MPD `connection_timeout`).