Android companion app for Any Player, built with Kotlin + Jetpack Compose + Media3.
This app targets phone/tablet and Android Auto-style media browsing, and includes provider integrations (Spotify/Jellyfin/Plex), local playlist persistence, and background media playback.
- Kotlin + Jetpack Compose
- Media3 (
ExoPlayer,MediaSession,MediaLibraryService) - Hilt (DI)
- Room (local storage)
- Retrofit/OkHttp
- Coroutines + Flow
- Optional Rust FFI shared library (
any_player_ffi_android)
app/— Android application moduledocs/— acceptance matrix, limitations, blockers, migration notes
- Linux/macOS/Windows with:
- Android Studio (or command-line Android SDK tools)
- Android SDK (API 35)
- JDK 17
- For Rust FFI builds (optional but enabled by default):
- Rust toolchain + Cargo
- Android NDK installed via SDK Manager
- Shared Rust workspace at
../any-player-shared-rust
Create/update local.properties in the repo root:
sdk.dir=/path/to/Android/Sdk(required)ndk.dir=/path/to/Android/Sdk/ndk/<version>(recommended for deterministic Rust cross-compile)spotifyClientId=<your_spotify_client_id>(optional at build time; needed for Spotify auth flow)
You can also pass spotifyClientId as a Gradle property:
-PspotifyClientId=...
Use this if you do not have the sibling Rust workspace available.
./gradlew :app:assembleDebug -PskipRustFfiBuild=trueThis is the default path and expects ../any-player-shared-rust.
./gradlew :app:assembleDebug./gradlew :app:installDebug -PskipRustFfiBuild=trueOr run from Android Studio using the app configuration.
Unit tests:
./gradlew :app:testDebugUnitTest -PskipRustFfiBuild=trueInstrumented tests (device/emulator required):
./gradlew :app:connectedDebugAndroidTest -PskipRustFfiBuild=true- Media browsing is exposed via
AnyPlayerMediaLibraryServicein the app manifest. - Service access control is enforced at runtime in
AnyPlayerMediaLibraryServicevia trusted-controller validation (onConnect/onGetSession). - Trusted controllers include the app itself, system UID/system apps, and package allowlist entries in
TRUSTED_CONTROLLER_PACKAGES. - If a specific head unit host cannot connect, add its package name to
TRUSTED_CONTROLLER_PACKAGESinapp/src/main/java/com/anyplayer/android/playback/AnyPlayerMediaLibraryService.kt. - OAuth deep-link callback for Spotify uses:
anyplayer://spotify-callback.
docs/android-acceptance-matrix.mddocs/android-known-limitations.mddocs/android-release-blockers.md
- Missing SDK/NDK errors: verify
sdk.dirandndk.dirinlocal.properties. - Rust build failures: confirm
../any-player-shared-rustexists, Cargo is installed, and NDK toolchains are available. - Spotify login not working: ensure
spotifyClientIdis set and redirect URI config matchesanyplayer://spotify-callback. - Android Auto discovery issues: confirm the app is installed with the latest manifest/service changes and test via DHU or compatible head unit.