• v2026.06.04
    android / Build + lint + test (push) Successful in 5m6s
    release / Build signed APK (tag releases only) (push) Successful in 4m42s
    release / Build + push container image (push) Successful in 14s
    Stable

    bvandeusen released this 2026-06-04 23:03:04 -04:00 | 112 commits to main since this release

    Same-day re-cut on the per-day mutable CalVer scheme. Sixth re-cut of v2026.06.04 — two evening on-device papercuts (notification art + false-offline) on top of the morning UPnP parity, afternoon offline-UX composite + server DRY, /healthz hysteresis hotfix, and Sonos queue resync + prefetcher batch.

    Evening papercuts

    1. Notification / lock-screen art now matches the in-app album cover (PR #84)

    The MediaController notification and lock-screen background showed a different album cover than the in-app surfaces for some tracks.

    • In-app covers come from TrackRef.coverUrl/api/albums/{id}/cover (server album-level art).
    • The notification art came from the stream's embedded ID3/FLAC tags (MediaMetadata.artworkData), because PlayerController.toMediaItem never set artworkUri. Media3's BitmapLoader prefers artworkData over artworkUri, and ExoPlayer extracts embedded picture frames into the live metadata. For tracks whose embedded art differs from the server album cover (compilations, re-grouped singles), the two surfaces disagreed.

    Fix: PlayerController.toMediaItem sets artworkUri to coverUrl (verified against Media3 1.10.1 source: MediaMetadata.populate() overwrites artworkUri + artworkData as an atomic pair, so the MediaItem URI clears the embedded bytes). PlayerFactory.buildBitmapLoader provides an OkHttp-backed CacheBitmapLoader so the authed placeholder.invalid cover URL resolves. MinstrelPlayerService attaches it via MediaSession.setBitmapLoader. Album cover now wins on every surface (notification, lock screen, BT/AVRCP, Auto, Pixel Watch).

    2. False "server offline" → playback "Source error" on a healthy LAN server (PR #85)

    The app reported the server offline while it wasn't; a streaming track failed with load_failed / "Source error", then recovered on its own.

    • ConnectivityObserver.online gated on NET_CAPABILITY_VALIDATED — Android's WAN internet-validation probe, not Minstrel reachability. A transient WAN/DNS blip drops VALIDATED while the LAN server stays reachable.
    • ServerHealthController flipped to Offline instantly (no debounce; the /healthz hysteresis only guards ServerDown), and OfflineGatedDataSource fast-failed the in-flight stream read → ExoPlayer SOURCE error.

    Fix: ConnectivityObserver requires INTERNET only, not VALIDATED — the /healthz poll (with its own failure hysteresis) is now the sole authority on whether Minstrel is reachable. Added a WARN-tier ServerHealth -> X transition log (the signal previously had zero instrumentation).


    For the morning / afternoon batches that make up the rest of v2026.06.04, see the same-day commits on main (PRs #80–#83).

    Verify on device

    • Play a track whose embedded tag art differs from its server album cover → notification / lock-screen background now matches the in-app cover.
    • During a Wi-Fi/WAN hiccup, adb logcat -s Minstrel shows ServerHealth staying Healthy (or ServerDown only after sustained /healthz failures) — never a Offline flip from a brief validation drop. Streaming a non-cached track no longer dies with "Source error" on a momentary blip.
    Downloads