• v2026.06.12 — UPnP/Sonos cast resilience (lock, drop-suppression, session adopt) + recommendation tuning
    android / Build + lint + test (push) Successful in 4m39s
    release / Build signed APK (tag releases only) (push) Successful in 4m31s
    release / Build + push container image (push) Successful in 15s
    Stable

    bvandeusen released this 2026-06-12 21:26:09 -04:00 | 50 commits to main since this release

    Per-day mutable CalVer, re-cut forward to 3e258507. A full day of Android UPnP/Sonos cast hardening on top of the morning's recommendation batch.

    Cast survives a locked screen (PR #97)

    While casting, the wrapped ExoPlayer is paused, releasing its WAKE_MODE_NETWORK WiFi/wake locks — so on a locked, on-battery phone the WiFi power-saved within seconds and starved the liveness poll, dropping a perfectly-healthy speaker. New CastNetworkLock (high-perf/low-latency WifiLock + partial WakeLock) held for the lifetime of a cast.

    Don't drop the speaker (or blast local audio) on a phone-side network gap (PR #98)

    A transient ServerDown gap (WiFi still associated) tripped the drop threshold and fell back to the local player — which started playing the song out of the phone while the Sonos was still streaming it. The drop is now gated on NetworkStatusController: only drop when the phone's network is Healthy. During a phone-side outage the route is held and the poll reconciles on recovery (a local fallback couldn't reach the server either).

    Adopt a running session instead of clear+reload (PR #98)

    Selecting a speaker that's already playing your queue (a session the phone got disconnected from but the speaker kept streaming) now attaches in place — syncs to its live track/position, no queue wipe, no jarring restart — and skip/seek drive its live queue. Falls through to the full reload only when it isn't your queue.

    Anti-stickiness + faster recovery (PR #98)

    • Powered-off speakers now leave the picker (lastSeen + post-scan prune) and the selection reverts to the phone, so a later play never targets a ghost route.
    • On network recovery, a held cast reconciles immediately rather than waiting for the next poll tick.

    Verify on device — on battery (USB masks the network-gap class)

    • Cast → unplug → lock → keeps playing.
    • Cast → brief network blip → Sonos keeps playing, phone does not blare local audio, reconciles on recovery.
    • Phone dropped but Sonos still playing → re-select the group → attaches to the live session, skip works (no restart).
    • Power a speaker off → reopen the picker → it disappears; selection falls back to phone.

    Also in this release (recommendation tuning)

    • You-might-like fallback (#790), taste 2b (taste_overlap arm), recommendation metrics (Settings → Recommendation metrics). Deferred: taste phase 3 (context).

    🤖 Generated with Claude Code

    Downloads