Skip to content

feat(android): real android app with printstream ui, working youtube playback and downloads - #8

Merged
Nxssie merged 11 commits into
mainfrom
feat/android-app
Sep 10, 2026
Merged

Nxssie merged 11 commits into
mainfrom
feat/android-app

Conversation

@Nxssie

@Nxssie Nxssie commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • Android app gets the PrintStream theme, a global YouTube/SoundCloud switcher in the header, custom bottom nav and back navigation that retraces tabs.
  • Now Playing has a three-state queue sheet (player / half / queue) with a full-bleed cover, a playing-from caption and a SoundCloud download button.
  • YouTube playback on Android now works: the stream resolver uses the VISIONOS InnerTube client with a visitor id, probes past the 1 MiB teaser boundary and replays the issuing client's user agent from ExoPlayer.
  • Library gains liked songs and artists tabs; YouTube subscriptions are filtered to actual music artists.
  • SoundCloud tracks can be downloaded as local audio on desktop and Android.

Test plan

  • Emulator: search, play and skip YouTube tracks that previously 403'd
  • Emulator: three sheet states, list-driven collapse, back gesture through tabs and sheet
  • Emulator: SoundCloud download from Now Playing lands in MediaStore Downloads
  • :desktop:compileKotlin and :android:app:assembleDebug pass
  • Phone: confirm full-length SoundCloud streams with a logged-in session

🤖 Generated with Claude Code

- api, auth, provider, models, Log and their tests now live in the
  shared JVM module so both desktop and the Android app consume them
- OkHttp replaces java.net.http everywhere (it only exists on API 33+;
  Wren supports API 26) through a shared util/Http helper
- AppDirs resolves config/state dirs per platform instead of inline
  user.home reads
- OAuthConfig replaces the desktop-only generated BuildConfig reference
- guard the desktop-only yt-dlp OAuth cache write so Android logins
  cannot crash on it
- StreamResolver keeps the 4h/20min cache and delegates to a pluggable
  backend: desktop keeps yt-dlp, Android uses InnerTube's player
  endpoint (ANDROID_VR client) and SoundCloud progressive transcodings
- falls back through audio/mp4 > audio > muxed formats, skipping
  cipher-only formats
StateFlow-based transport + observable state used by the Android
ExoPlayerEngine; the desktop FFmpegPlayer keeps its Compose-state API
- search/discover/now playing/player bar composables with the desktop
  design tokens, accounts dialog and a SoundCloud web login route
  (WebView callback interception, popup hosting, desktop UA)
- ExoPlayerEngine implements PlayerEngine; WrenPlaybackService keeps a
  MediaSession-backed foreground notification (airpods/lockscreen
  controls)
- adaptive launcher icon (W03 print, monochrome included) and alpha
  notification icon; POST_NOTIFICATIONS requested at startup
- bundled Google OAuth client baked from env at build time; AppDirs
  targets app-private storage; proguard file added
- Library was playlists only; songs and artists come through the provider
  contract so each platform opts in via supportsArtists/supportsLibrary
- Shared DownloadManager copies the same progressive stream the player uses,
  so no extra binary is needed; destinations are per platform (Music dir on
  desktop, MediaStore Downloads on Android)
- ANDROID_VR is bot-checked for many music videos and IOS hands out teaser
  URLs that 403 past the first MiB; VISIONOS with a scraped visitor id (the
  same default yt-dlp uses) returns full-length, cipher-free URLs
- Probe one byte past the teaser boundary so capped URLs fall through to the
  next client, and replay the issuing client's user agent from ExoPlayer
- Surface the failure reason in the player bar instead of skipping silently
- Carry a queue title in the PlayerEngine contract for the now playing caption
- The Data API has no artist flag, so each subscribed channel is checked
  against YouTube Music's browse header (immersive = artist, visual = channel)
- Platform switcher moves from Search into the header so YouTube/SoundCloud
  is one tap away on every browse tab, with per-platform session dots
- Custom bottom nav, square shapes and system bars that follow the theme,
  replacing the stock Material chrome
- System back retraces visited tabs and open playlists instead of quitting
- Queues carry their origin (playlist, mix, search) for the now playing caption
- Player, half and queue anchors driven by one progress value: full-bleed
  cover backdrop, controls anchored above the sheet, compact header when open
- Download button for SoundCloud tracks; back collapses the sheet first
@Nxssie
Nxssie merged commit e48821b into main Sep 10, 2026
5 checks passed
@Nxssie
Nxssie deleted the feat/android-app branch September 10, 2026 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant