Skip to content

epochaudio/RoonCoverArt_Android

Repository files navigation

CoverArt for Android (v2.3.6)

English | 中文

English

CoverArt is an Android display client for the Roon ecosystem. It is designed for always-on screens and TV-class devices, showing current album art in full screen and switching to an art wall when playback is idle.

What It Does

  • Shows now playing title, artist, album, and high-resolution cover art from Roon Core.
  • Keeps a clean visual mode by hiding normal status text; only actionable warnings are shown as overlay.
  • Automatically enters a 15-cover Art Wall when playback stops, then returns to single-cover mode when music resumes.
  • Supports both physical media keys and touch gestures for playback control.
  • Uses local cache and color-adaptive background/text styling for stable long-running display behavior.
  • Portrait now-playing uses a poster-style composition with a cover-first layout, bottom metadata band, and a conservative Balanced / Airy cover profile switch for sparse bright artwork.

Playback Controls

  • Touch gestures:
    • Swipe left: next track
    • Swipe right: previous track
    • Swipe up: pause
    • Swipe down: play
  • Media keys:
    • Play/Pause key multi-click: single=toggle, double=next, triple=previous
    • Media Next / Previous / Play / Pause / Stop supported
    • Silent volume up/down and mute handling

Requirements

  • Android 8.0 (API 26) or newer
  • Roon Core on the same LAN
  • Extension API enabled in Roon
  • Stable Wi-Fi network

Build & Install

  1. Open in Android Studio and run debug build, or use CLI: ./gradlew assembleDebug
  2. Release APK (v2.3.6) is published as CoverArt-2.3.6-debug.apk; local debug builds are generated at app/build/outputs/apk/debug/app-debug.apk
  3. Install the APK to your Android device.
  4. Ensure device and Roon Core are in the same LAN.

Setup in Roon

  1. Open Roon desktop app.
  2. Go to Settings > Extensions.
  3. Find CoverArt_Android and enable it.
  4. Select or confirm playback zone if needed.

How to Use

  1. Launch CoverArt.
  2. Wait for auto-discovery and auto-pairing.
  3. During playback, the app shows single-cover now playing view.
  4. When playback is idle/stopped, the app transitions to Art Wall automatically.
  5. Use touch gestures or media keys to control playback directly from the display device.

Version

See CHANGELOG.md for release history.

  • 2.3.6 (Latest)
    • Bound current album-art requests to the active playback identity so stale image responses cannot overwrite the current track display
    • Added trackId + imageKey validation for current album-art responses
    • Synchronized transition metadata binding with internal playback state
    • Added JVM regression coverage for current album-art response guarding
  • 2.33
    • Migrated metadata text policy decisions to a TrackTextMeasurer abstraction backed by Android StaticLayout
    • Added balanced line breaking and safe second-pass shrink-wrap for tighter portrait metadata width
    • Extracted cover, portrait profile, and Art Wall layout policies into explicit ui/layout resolvers with JVM coverage
    • Cleaned up completed maintenance docs and archived historical plans
  • 2.32
    • Added explicit timeout cleanup for image requests so stale cover/preview fetches cannot block later retries
    • Serialized WebSocket frame writes through a dedicated outbound writer to avoid concurrent writes interleaving on the socket
    • Made message processor shutdown non-blocking during Activity teardown to reduce ANR risk
    • Added regression coverage for image request lifecycle, WebSocket outbound writes, message processor cleanup, and subscription lifecycle handling
  • 2.31
    • Refined portrait now-playing into a poster-style layout for 9:16 displays, with a bottom-aligned metadata band, left-aligned hierarchy, and warmer text tones for long-distance readability
    • Added conservative PortraitCoverProfile routing plus CoverCompositionAnalyzer heuristics so bright sparse covers can opt into an Airy portrait treatment without affecting landscape mode
    • Simplified metadata text rendering in TrackTextSceneView to a single-pass draw path, removing the shadow/fake-bold edge halo that could read like an outline on low-PPI framed displays
    • Added JVM regression coverage for cover composition classification while keeping existing metadata layout policy tests green
  • 2.30
    • Replaced metadata TextView rendering with a measured scene pipeline built from TrackTextLayoutPolicy, AndroidTrackTextLayoutEngine, and TrackTextSceneView
    • Rebuilt portrait and landscape metadata layout around a cover-first LayoutSpec with short-edge-driven spacing and readability baselines
    • Added contentWidthPx shrink-wrap and transition-time width freezing so short titles can breathe without horizontal jitter during skips
    • Routed metadata transitions through scene interpolation and aligned timing, stagger, and shift tokens to remove mid-animation text mutation
    • Migrated metadata colors to explicit TrackTextPalette ownership and isolated statusText overlay coloring from album-art palette updates
    • Added JVM regression coverage for layout policy sizing, mixed-language and low-density readability, and scene transition state handoff
  • 2.29
    • Hardened WebSocket, subscription registry, and connection-monitor lifecycle handling to reduce race conditions and leaks
    • Simplified message processing into a single-threaded execution path for more predictable MOO handling
    • Extracted MOO dispatch, image response processing, palette handling, and queue coordination into dedicated collaborators
    • Added parser/input hardening for oversized Content-Length and IPv6 host parsing
    • Expanded regression coverage for routing, parser limits, subscription removal, and connection-input parsing
  • 2.28
    • Optimized Art Wall loading path: moved bitmap decoding off the main thread to reduce UI stutter
    • Improved idle/playback switching stability by replacing delayed Timer switching with main-thread scheduling
    • Added Art Wall snapshot/restore on rotation and size-aware bitmap caching for faster orientation changes
    • Refactored cover display / art wall / layout responsibilities into dedicated managers for maintainability
    • Added unit tests for Art Wall rotation pool logic
  • 2.26
    • Improved first-pairing authorization hint reliability when registration responses are delayed or missing
    • Added fallback handling for empty registration responses to always surface Roon-side authorization guidance
    • Hardened register response correlation to avoid missing pairing-state transitions
    • Prevented bottom system-gesture area from triggering swipe-up pause when exiting app
  • 2.25
    • Premium UI Refactoring: Extracted dimensions into centralized UIDesignTokens
    • Adaptive Static Typography: Replaced marquee effects with intelligent multi-line layout and kerning for perfect immersion
    • Art Wall Rebirth: Replaced rigid 3D card flips with elegant cross-fade "breathing" transitions and soft elevations
  • 2.24
    • Improved track transition aesthetics with physics-based spring animations
    • Added cascade text animation and Z-axis drop effect for cover art
    • Perfected audio-visual synchronization by strictly aligning with playing state
    • Added async image rendezvous handling for slow networks
    • Improved art wall idle detection and timeout suppression
  • 2.23
    • Added touch gesture playback controls (left/right/up/down swipes)
    • Added track transition animation feedback when changing tracks
    • Kept clean status overlay policy and existing keyboard/media-key control path
  • 2.21
    • Switched user-facing UI status text to English
    • Added alert-only status overlay visibility strategy
    • Improved first-pairing authorization hint behavior

中文

CoverArt 是面向 Roon 生态的 Android 展示端应用。 它面向常亮大屏/电视类设备,主界面专注展示当前播放专辑封面,播放停止时自动进入艺术墙模式。

功能简介

  • 实时展示 Roon 当前播放信息:歌曲名、艺术家、专辑名、高清封面。
  • 状态提示采用“告警优先”策略:正常播放时保持画面干净,仅在需要处理的问题场景显示提示层。
  • 播放停止后自动进入 15 宫格艺术墙;恢复播放后自动回到单封面模式。
  • 同时支持物理媒体键与触摸手势控制播放。
  • 本地缓存与主色调自适应背景/文字,提升长期运行稳定性与观感一致性。
  • 竖屏播放态采用更接近画框海报的 cover-first 构图,底部信息带左对齐,并通过保守的 Balanced / Airy 封面分流适配高亮度、大留白封面。

播放控制

  • 触摸手势:
    • 左滑:下一曲
    • 右滑:上一曲
    • 上滑:暂停
    • 下滑:开始播放
  • 物理媒体键:
    • 播放键多击:单击=播放/暂停,双击=下一曲,三击=上一曲
    • 支持 Next / Previous / Play / Pause / Stop
    • 支持静默音量增减与静音

使用条件

  • Android 8.0(API 26)及以上
  • 与 Roon Core 在同一局域网
  • 已在 Roon 中启用 Extension API
  • 网络连接稳定

构建与安装

  1. 使用 Android Studio 打开工程并运行,或命令行执行:./gradlew assembleDebug
  2. Release APK(v2.3.6)发布为 CoverArt-2.3.6-debug.apk;本地 debug 构建产物位于 app/build/outputs/apk/debug/app-debug.apk
  3. 安装生成的 APK 到 Android 设备。
  4. 确保设备与 Roon Core 在同一局域网。

Roon 侧配置

  1. 打开 Roon 桌面端。
  2. 进入 设置 > 扩展
  3. 找到 CoverArt_Android 并启用。
  4. 如有需要,在扩展设置中确认播放区域(Zone)。

使用指南

  1. 启动 CoverArt。
  2. 等待自动发现/自动配对。
  3. 播放中显示单封面 Now Playing。
  4. 停播后自动切换为艺术墙。
  5. 可直接在屏幕上滑动控制播放,或使用媒体键操作。

版本信息

完整版本记录见 CHANGELOG.md

  • 2.3.6(最新)
    • 将当前封面请求绑定到正在播放的曲目身份,避免陈旧图片响应覆盖当前曲目展示
    • 为当前封面响应增加 trackId + imageKey 校验
    • 让转场 metadata 绑定同步写回内部播放状态
    • 补充当前封面响应 guard 的 JVM 回归测试
  • 2.33
    • 将 metadata 文本策略判断迁移到 TrackTextMeasurer 抽象,并由 Android StaticLayout 提供真实测量
    • 增加 balanced line breaking 与安全二段式 shrink-wrap,让竖屏 metadata 宽度更贴合内容
    • 将封面、竖屏 profile 和 Art Wall 布局策略提取到明确的 ui/layout resolver,并补充 JVM 覆盖
    • 清理已完成维护文档,并归档历史计划
  • 2.32
    • 为图片请求增加显式超时清理,避免陈旧封面/预览请求阻塞后续重试
    • 通过独立出站 writer 串行化 WebSocket frame 写入,避免多线程并发写同一 socket 时帧内容交错
    • Activity 销毁时改为非阻塞关闭消息处理器,降低生命周期回调触发 ANR 的风险
    • 补充图片请求生命周期、WebSocket 出站写入、消息处理器清理与订阅生命周期相关回归测试
  • 2.31
    • 将竖屏 Now Playing 收敛为更适合 9:16 画屏的海报式布局:封面优先、底部信息带贴底、文字层级左对齐,并统一为偏暖文字色提升远看可读性
    • 新增保守的 PortraitCoverProfile 分流与 CoverCompositionAnalyzer 轻量封面分析,让高亮度、大留白封面进入 Airy 竖屏样式,同时不影响横屏布局
    • TrackTextSceneView 改为单层文字绘制,移除阴影叠画和标题 fake bold,降低低 PPI 画屏上容易被看成“文字有边框”的暗边感
    • 补充封面分类相关 JVM 回归测试,并保持现有 metadata 布局策略测试通过
  • 2.30
    • TrackTextLayoutPolicyAndroidTrackTextLayoutEngineTrackTextSceneView 组成新的测量式 scene 文本渲染链路,替换元数据 TextView 直绘
    • 围绕 cover-first LayoutSpec 重写横竖屏元数据布局,采用短边驱动的间距与远距离可读性基线
    • 新增 contentWidthPx 基础 shrink-wrap,并在转场期间冻结 metadata 容器宽度,避免切歌时横向抖动
    • 文本转场改为 scene 插值驱动,并统一时长、级联延迟与位移 token,移除动画中途直接改文案
    • 元数据配色迁移为显式 TrackTextPalette,同时把 statusText overlay 颜色所有权从专辑主色联动里剥离
    • 补充布局策略、低密度大屏/中英文混排可读性,以及 scene 转场状态衔接的 JVM 回归测试
  • 2.29
    • 强化 WebSocket、订阅注册表与连接监控生命周期处理,降低竞态与资源泄漏风险
    • 将消息处理链路收敛为单线程串行执行,提升 MOO 协议处理可预测性
    • 拆出 MOO 路由、图片响应处理、主色调管理、队列协调等独立协作类,降低 MainActivity 复杂度
    • 增强协议与输入健壮性,补上超大 Content-Length 限制与 IPv6 地址解析
    • 补充路由、解析上限、订阅移除和连接输入解析相关回归测试
  • 2.28
    • 优化艺术墙图片加载链路:Bitmap 解码移出主线程,降低卡顿
    • 优化停播/恢复切换稳定性:延迟切换改为主线程调度,降低竞态风险
    • 新增横竖屏切换时的艺术墙快照恢复与尺寸感知缓存,加快旋转恢复速度
    • 拆分封面显示 / 艺术墙 / 布局编排职责,提升代码可维护性
    • 新增艺术墙轮换池逻辑单元测试,增强回归保护
  • 2.26
    • 优化首次配对授权提示可靠性,覆盖注册响应延迟/丢失场景
    • 新增注册空响应兜底处理,确保能提示去 Roon 侧完成授权
    • 强化 register 响应关联,降低配对状态丢失风险
    • 修复底部系统手势区域误触发“上滑暂停”,避免退出应用时误暂停播放
  • 2.25
    • 高级视觉重构 (Premium UI):引入 UIDesignTokens 标准化设计语言,剥离硬编码约束
    • 沉静式排版:全面消除跑马灯,引入自适应折行、文字安全边距与画廊级字间距
    • 艺术墙 (Art Wall) 原生质感:移除生硬的 3D 翻转卡片与 2px 勾边,重制为极具呼吸感的平滑交叉渐变 (Cross-fade) 与弥散阴影
  • 2.24
    • 提升切歌动效手感,引入物理弹簧动画 (SpringAnimation)
    • 增加文字错落浮现与封面 Z 轴沉缩呼吸效果
    • 极其精准的音画同步机制,严格对齐 playing 状态
    • 新增异步超清图片加载过程的平滑遮罩处理
    • 优化弱网及缓冲时的艺术墙防切误判
  • 2.23
    • 新增触摸手势播放控制(左/右/上/下滑)
    • 新增切歌动画反馈
    • 保留并兼容原有媒体键控制与状态提示策略
  • 2.21
    • UI 状态文案统一英文
    • 增加仅告警可见的状态提示层策略
    • 优化首次配对授权提示逻辑

支持

About

CoverArt 是面向 Roon 生态的 Android 客户端,专注在大屏设备上实时展示当前播放的专辑封面,并在闲置时切换到艺术墙模式,打造沉浸式的客厅音乐体验。

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors