Private
Public Access
The cut is per account, not per device: a file request from any device signed in to the same account (another phone, an iPod, the Mac) cut this phone's stream. The player's own stream now also asks for the file as a download (?download=1), which Plex leaves out of that rule; the plain address follows for servers that refuse downloads. Transcodes aren't affected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
76 lines
4.7 KiB
Markdown
76 lines
4.7 KiB
Markdown
# Plexamp Lite (Android) — spec
|
||
|
||
The short contract for working on this app. `README.md` is the user guide; this file says what the app is
|
||
for, what limits it lives within, and what must not break.
|
||
|
||
## Goal
|
||
|
||
A Plexamp-style Plex music player for the Samsung Galaxy Mini that keeps playing reliably at home, away and
|
||
over a Bluetooth speaker.
|
||
|
||
## Target and hard limits
|
||
|
||
- Samsung Galaxy Mini GT-S5570: Android 2.2/2.3 (API 8), 240×320 ldpi, 600 MHz ARMv6, 384 MB RAM; any 2.2+
|
||
phone. A second build for Android 4.1+ (API 16: Xperia J, Galaxy S II), one per Android level, never per phone.
|
||
- Native Java (this app uses XML layouts), no libraries beyond the bundled Bouncy Castle TLS; the Android 4.1 build
|
||
adds ExoPlayer 2.18.7 (+ Guava), shrunk by R8.
|
||
- Galician by default, English in Settings. All text in `tools/strings.py`, which generates
|
||
`res/values*/strings.xml`. The connection log stays in English.
|
||
- Plays MP3/AAC/Vorbis directly; FLAC, ALAC and the rest are transcoded to MP3 by the server.
|
||
|
||
## Current scope (1.14)
|
||
|
||
- Sign in with a plex.tv/link PIN (or a manual address + token). Owned and shared servers and libraries.
|
||
- Connection picking: last good one first, then LAN HTTP, LAN HTTPS (`plex.direct`), remote HTTPS, Relay
|
||
(capped at 192 kbps). Secure addresses tried one at a time; re-checked on network changes.
|
||
- Bundled TLS 1.2/1.3 with session resumption; a loopback `StreamProxy` feeds the media player.
|
||
- Quality per network (home, away, Bluetooth cap), read-ahead of the next two tracks, stall and failure
|
||
recovery (re-pick, then download first), resume after short Bluetooth drop-outs.
|
||
- Home radios and shelves, Artists/Albums/Playlists, Search, artist/album/playlist pages, Now Playing, Up
|
||
Next queue (survives restarts), sleep timer, love, downloads to SD card with offline play reporting.
|
||
- Headset and Bluetooth buttons; pauses for calls and unplugging. Plays reported to Plex (not while
|
||
`PlexampLite-noreport` is on the SD card: for tests against a real server).
|
||
- Lyrics in Now Playing (as in the Mac app): a lasting on/off; timed lyrics follow and seek; plain text scrolls.
|
||
- Home-screen widget (both builds).
|
||
- Android 4.1 build: ExoPlayer with gapless hand-over to read-ahead/downloaded files, notification and lock screen
|
||
with art and buttons, resizable widget, Holo, ⋮ without a Menu key, metered networks.
|
||
|
||
## Out of scope
|
||
|
||
- On the Android 2.x build: gapless playback and notification playback buttons (Android 2.x can't).
|
||
- Video, photos.
|
||
|
||
## Must not break
|
||
|
||
- Package `com.minamp` and `signing/minamp.keystore` (password `minamp123`): updates install over Minamp.
|
||
- Signing: `tools/signapk.py` (classic SignApk v1); never `jarsigner`.
|
||
- `src/com/minamp/net/` is the origin of `tlskit`; keep the two in step (change `../tlskit`, reinstall).
|
||
- This repo's `tools/setup_toolchain.sh`, `make_roots.py` and `signapk.py` prepare the toolchain all the
|
||
Galaxy Mini apps use: changes there affect every app.
|
||
- Installs to internal storage (SD-card installs get killed during USB sharing).
|
||
- Every request for a track's file (playing, read-ahead, downloads) uses `Library.downloadUrls` (`?download=1`
|
||
first): Plex cuts an account's file stream when any device on that account starts another, except downloads.
|
||
- `platform/api8` and `platform/api16` keep the same `Platform` methods; shared code calls no API the API 8 jar
|
||
lacks (the api8 compile and Dalvik check catch it). Each build's `versionCode` is the manifest's × 100 + level,
|
||
same key; both APKs are listed in `../tenda-lite/repo/apps.json`.
|
||
- The Android 4.1 build targets API 16: no `clipPath` in drawing (the GPU can't before 4.3), and network on the
|
||
main thread is allowed in `Platform.init` (the shared code closes connections there).
|
||
|
||
## Code map
|
||
|
||
`PlayerService` (playback, recovery, gapless) · `Engine` (`MediaPlayerEngine`; `ExoEngine` in platform/api16) ·
|
||
`Platform` (per level) · `PlayerWidget` + `PlayerViews` · `Lyrics` + `LyricsView` + `util/Lrc` · · `PlayQueue` · `Downloads` · `plex/` (`Plex`, `Server`, `Library`,
|
||
`Item`) · `net/` (`Http`, `CertVerifier`, `StreamProxy`, `Threads`, `DiagLog`) · activities Home, Browse,
|
||
NowPlaying, Queue, Search, Setup, Downloads.
|
||
|
||
## Build, test, release
|
||
|
||
- `tools/setup_toolchain.sh` and `tools/fetch_exoplayer.sh` once, then `./build.sh` → `build/PlexampLite.apk`
|
||
and `build/PlexampLite-api16.apk`.
|
||
- Tests on the desktop JVM: `PlexTest` with `test/mock_plex.py`, `QueueTest`, `LyricsTest`, `PreferHomeTest` with
|
||
`test/identity_server.py`, `NetTest`, `HandshakeProfile`.
|
||
- Release: raise `versionCode`/`versionName`, build, add `changes` in `../tenda-lite/repo/apps.json`, commit
|
||
and push, `../tenda-lite/repo/publish.sh`.
|
||
- Siblings for iPod, Mac and Linux (`plexamp-lite-ios`, `-mac`, `-linux`) share behaviour; fixes are often
|
||
backported between them.
|