- Kotlin 99.8%
- Just 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| app | ||
| gradle | ||
| .gitignore | ||
| build.gradle.kts | ||
| gradle.properties | ||
| gradlew | ||
| Justfile | ||
| README.md | ||
| settings.gradle.kts | ||
VIBE CODING WARNING
This project was written completely by an LLM (Muse Spark 1.3 in OpenCode).
Subsonic TV Client
Simple Subsonic / OpenSubsonic client for Android TV (Google TV), written in Kotlin.
Features
- Login form: server URL + username + password (validated with
ping, saved in DataStore) - Home: recent albums grid (
getAlbumList2) + playlists row (getPlaylists, covers viagetCoverArt) - Album / playlist detail: song list, tap to play
- Queue: tapping a song plays it and queues the rest of the list in order, auto-advances, with Prev / Play-Pause / Next and an Up-Next list
- Mini Now-Playing bar on all screens + full player screen
- Playback via Media3 ExoPlayer, streaming via
stream.view - Auth via OpenSubsonic token (
md5(password + salt)), works with Subsonic, Navidrome, Gonic, Airsonic-Advanced, etc.
Requirements
- JDK 17+
- Android SDK with
platforms;android-35+build-tools;35.0.0(install via Android Studio orsdkmanager) - The project ships a Gradle wrapper pinned to Gradle 9.5.1, which pairs
with the configured Android Gradle plugin 8.13.2 — always build with
./gradlew, not a systemgradle(e.g. Gradle 9.7 breaks AGP 8.x).
SDK location
Set one of these (this machine uses local.properties, which is gitignored):
# local.properties
sdk.dir=$HOME/Android/Sdk
or export ANDROID_HOME=$HOME/Android/Sdk.
Run
- Open this folder in Android Studio (it will pick up the wrapper automatically).
- Let Gradle sync.
- Run
appon an Android TV emulator (e.g. Pixel TV 1080p, API 35) or a real Google TV device. - Enter server URL (e.g.
https://music.example.com), username, password.
Build APK (verified working)
./gradlew :app:assembleDebug
# apk at app/build/outputs/apk/debug/app-debug.apk
Release build (signed)
Release APKs must be signed. This project reads signing credentials from a
gitignored keystore.properties next to the root build.gradle.kts:
storeFile=release.keystore # path relative to the app/ module dir
storePassword=...
keyAlias=subsonictv
keyPassword=...
A keystore + matching keystore.properties already exist on this machine.
To create your own on a fresh setup:
keytool -genkeypair -keystore app/release.keystore -alias subsonictv \
-keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Subsonic TV"
# then fill in keystore.properties with your passwords
Then:
./gradlew :app:assembleRelease
# signed apk at app/build/outputs/apk/release/app-release.apk
Without keystore.properties the release build still runs but produces an
unsigned APK that Android will refuse to install.
Back up
app/release.keystore+keystore.propertiessomewhere safe. Lose them and you can never ship an update for the same app id again.
Note:
Deprecated Gradle features were used... incompatible with Gradle 10at the end of a successful build is a harmless upstream warning from the Android Gradle plugin, not an error.
Lint
ktlint --android "app/src/**/*.kt"
Notes / next steps
- Covers use Coil; stream URLs embed short-lived auth tokens.
- Player is process-scoped; add a
MediaSessionService+ notification if you want background playback after leaving the app. getAlbumList2type is"recent"; change tonewest/random/mostPlayedinHomeViewModelif you prefer.- The TV banner currently reuses the adaptive launcher icon; swap in a
wide
drawable/tv_banner(320x180) in the manifest if you want a proper Leanback banner.