Private
Public Access
Plexamp Lite 1.14: Android 4.1 build with ExoPlayer, lyrics, home-screen widget
- One build per Android level, as in Tenda: build/PlexampLite.apk (Android 2.2+, versionCode 1508) and build/PlexampLite-api16.apk (Android 4.1+, 1516), from shared src/ plus platform/api8 or platform/api16. - Android 4.1 build: ExoPlayer 2.18.7 behind a small Engine interface (gapless hand-over to read-ahead and downloaded files, a longer buffer, MediaPlayer fallback for tracks it can't decode), a notification and lock screen with art and buttons, a resizable widget, Holo, a menu button without a Menu key, metered networks. R8 shrinks ExoPlayer and Guava (tools/fetch_exoplayer.sh, tools/r8-rules.pro). - Both builds: lyrics in Now Playing as in the Mac app (timed lyrics follow and seek), a home-screen widget, media play/pause keys, the moon icon drawn without clipPath. - PlexampLite-noreport on the SD card stops play reports, for tests against a real server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2e7476669e
commit
13f29e26c4
39 files changed
+1685
-119
No files matched your search
@@ -1,8 +1,9 @@
|
||||
# Plexamp Lite
|
||||
|
||||
A small Plexamp-style music player for Plex, built for the Samsung Galaxy Mini (GT-S5570:
|
||||
Android 2.2/2.3, 240×320 ldpi screen, 600 MHz ARMv6, 384 MB RAM). Runs on any Android 2.2+ phone.
|
||||
Formerly Minamp (the package name, `com.minamp`, stays so updates install over it).
|
||||
Android 2.2/2.3, 240×320 ldpi screen, 600 MHz ARMv6, 384 MB RAM). Runs on any Android 2.2+ phone, and comes
|
||||
in a second build for Android 4.1 and later (Xperia J, Galaxy S II…) that uses what those phones can do: see
|
||||
*Android 4.1 build*. Formerly Minamp (the package name, `com.minamp`, stays so updates install over it).
|
||||
|
||||
## Language
|
||||
|
||||
@@ -14,7 +15,7 @@ log stays in English since it's meant for troubleshooting.
|
||||
## Install
|
||||
|
||||
1. On the phone: **Settings → Applications → Unknown sources** (tick it).
|
||||
2. Copy `PlexampLite.apk` to the SD card (USB cable, or download it in the browser) and open it
|
||||
2. Copy `PlexampLite.apk` (Android 4.1+: `PlexampLite-api16.apk`; Tenda picks the right one by itself) to the SD card (USB cable, or download it in the browser) and open it
|
||||
with a file manager, or from a computer: `adb install PlexampLite.apk`.
|
||||
3. Plexamp Lite installs to internal storage (about 1 MB): an app on the SD card is killed whenever the
|
||||
phone shares its SD card over USB, which stopped the music.
|
||||
@@ -71,7 +72,9 @@ clock has been reset to before 2024 the certificate date check is skipped rather
|
||||
* A Bluetooth speaker that drops its link for a moment pauses Plexamp Lite, which resumes by itself if the
|
||||
speaker is back within 20 s. Why playback paused or stopped is written to the connection log,
|
||||
which also goes to logcat (tag `PlexampLite`, readable over USB with `adb logcat`).
|
||||
* Plays are reported to Plex (Now Playing in the Plex dashboard, play counts, resume position).
|
||||
* Plays are reported to Plex (Now Playing in the Plex dashboard, play counts, resume position). For testing
|
||||
against a real server, an empty file named `PlexampLite-noreport` at the top of the SD card turns that off
|
||||
(`adb shell touch /sdcard/PlexampLite-noreport`; delete it afterwards).
|
||||
|
||||
## Features
|
||||
|
||||
@@ -82,6 +85,12 @@ clock has been reset to before 2024 the certificate date check is skipped rather
|
||||
* Long-press anything: Play next, Add to queue, Go to album/artist, Love.
|
||||
* Now Playing: big art on a backdrop coloured from the cover, seek bar, shuffle, repeat
|
||||
(queue/track), love, sleep timer (15–90 min or end of track), where it's streaming from.
|
||||
* **Lyrics**: the microphone button in Now Playing shows the track's lyrics from Plex in place of the art (as in
|
||||
the Mac app). It's a lasting setting: it stays on for the following tracks and after restarts. Timed (LRC)
|
||||
lyrics follow the song with the current line lit (tap a line to jump there; scrolling by hand pauses the
|
||||
follow for a few seconds); plain-text lyrics just scroll. With several versions, timed ones win, else the
|
||||
longest text (a local `.txt` can be a broken copy).
|
||||
* **Home-screen widget** (4×1): art, title, artist, previous / play-pause / next; tap the art for Now Playing.
|
||||
* Up Next queue: jump, play next, remove, clear; the queue and position survive restarts.
|
||||
* Downloads for offline listening: long-press a track, album, artist or playlist -> *Download*;
|
||||
*Menu -> Downloads* shows progress, space used and free, play/shuffle, retry and remove. Files go to
|
||||
@@ -92,15 +101,47 @@ clock has been reset to before 2024 the certificate date check is skipped rather
|
||||
* Wired headset button: 1 click play/pause, 2 next, 3 previous; Bluetooth media keys;
|
||||
pauses for calls and when headphones are unplugged.
|
||||
|
||||
## Android 4.1 build
|
||||
|
||||
One build per **Android level**, never per phone (the same pattern as Tenda): `build/PlexampLite.apk` for
|
||||
Android 2.2+ and `build/PlexampLite-api16.apk` for 4.1+, from the same source, package and key.
|
||||
`versionCode` is the manifest's × 100 + the level (15 → 1508 and 1516), so a phone that moves up a level
|
||||
gets the newer build as an ordinary update, and Tenda gives each phone the build for its Android. Everything is
|
||||
shared in `src/`; what only one level can do is in `platform/api8/…/Platform.java` and
|
||||
`platform/api16/…/Platform.java` (the same methods; keep them in step), plus `platform/api16/res`, which
|
||||
overrides a few resources. The Android 4.1 build adds:
|
||||
|
||||
* **ExoPlayer 2.18** (`platform/api16/…/ExoEngine.java`) instead of Android's MediaPlayer, behind the small
|
||||
`Engine` interface the player service uses (`MediaPlayerEngine` on Android 2.x):
|
||||
* **gapless playback**: when the next track's file is already here (read ahead or downloaded), it's queued
|
||||
in the player and starts with no gap;
|
||||
* a buffer of up to 3 minutes instead of seconds, so Wi-Fi gaps don't silence it;
|
||||
* errors that say what failed. A track ExoPlayer can't decode is retried with Android's MediaPlayer.
|
||||
Read-ahead, the stream proxy, the transcodes and the recovery steps are the same in both builds.
|
||||
* A **notification** with the art and ⏮ ⏯ ⏭ × (pull it down for a larger one); swiping it away while paused stops.
|
||||
* **Lock-screen controls** with the art (RemoteControlClient).
|
||||
* The **widget** can be resized; two rows or taller shows a larger layout.
|
||||
* Android 4's **Holo** dialogs and text fields; a ⋮ button on phones without a Menu key.
|
||||
* **Metered networks**: a phone's Wi-Fi hotspot counts as away, like mobile data.
|
||||
|
||||
The Galaxy Mini's build is unchanged in how it plays, and also got the widget and the lyrics.
|
||||
|
||||
## Building (no Android SDK needed)
|
||||
|
||||
```
|
||||
tools/setup_toolchain.sh # once: fetches aapt2, the API 8 android.jar, builds dx, renames Bouncy Castle
|
||||
./build.sh # -> build/PlexampLite.apk
|
||||
tools/fetch_exoplayer.sh # once: ExoPlayer 2.18.7 + Guava (checksums pinned) into ~/android-toolchain
|
||||
./build.sh # -> build/PlexampLite.apk (Android 2.2+) and build/PlexampLite-api16.apk (4.1+)
|
||||
./build.sh 16 # one level only
|
||||
```
|
||||
|
||||
`build.sh` runs `aapt2` (resources), `javac` (Java 8 bytecode checked against the API 8
|
||||
`android.jar`), `dx` (dex 035) and `tools/signapk.py`, which writes the v1 signature in the
|
||||
Also needed for the Android 4.1 build: the API 16 `android.jar` in `~/android-toolchain/platforms/android-16/`,
|
||||
R8 (`d8.jar` from build-tools 34, in `~/android-toolchain/calendar-tools/`) and a JDK 11+ (`build.sh` finds
|
||||
Homebrew's openjdk@17). ExoPlayer 2.18.7 is the newest that needs only Guava; R8 (`tools/r8-rules.pro`) keeps
|
||||
the app whole and shrinks ExoPlayer and Guava to what it uses, in one dex.
|
||||
|
||||
Per level `build.sh` runs `aapt2` (resources), `javac` (Java 8 bytecode checked against that level's
|
||||
`android.jar`), then for Android 2.x the Dalvik 2.x link check and `dx` (dex 035), for 4.1 R8; then `tools/signapk.py`, which writes the v1 signature in the
|
||||
classic Android SignApk format and aligns the APK. (Modern `jarsigner` output does *not* install on
|
||||
Android 4.2 and older: it names digests `SHA-1-Digest` and labels the PKCS#7 signer algorithm in a
|
||||
way old `JarUtils` can't read, so the phone treats the APK as unsigned.) The debug key in `signing/` (password `minamp123`) is what this APK is
|
||||
@@ -113,6 +154,8 @@ Tests (desktop JVM, no device):
|
||||
untrusted-root rejection, browsing, search, artwork, and the stream proxy (Range requests over
|
||||
TLS, de-chunking transcodes, aborting).
|
||||
* `test/QueueTest.java`: shuffle/unshuffle, repeat modes, play next, remove, move, clear.
|
||||
* `test/LyricsTest.java`: LRC (several stamps a line, offsets, word stamps) and plain-text lyrics
|
||||
(`javac -d /tmp/lt src/com/minamp/util/Lrc.java test/LyricsTest.java && java -cp /tmp/lt LyricsTest`).
|
||||
* `test/PreferHomeTest.java` + `test/identity_server.py`: after being away, the home address wins
|
||||
again as soon as it answers.
|
||||
* `test/NetTest.java`: the bundled TLS + HTTP client against real servers; `test/HandshakeProfile.java`
|
||||
@@ -120,5 +163,7 @@ Tests (desktop JVM, no device):
|
||||
|
||||
## Limits
|
||||
|
||||
* No gapless playback (Android 2.2/2.3 have no API for it).
|
||||
* Notification has no playback buttons (pre-Android 3 can't); tap it to open Now Playing.
|
||||
* Android 2.x build: no gapless playback (no API for it), and the notification has no playback buttons
|
||||
(pre-Android 3 can't): tap it to open Now Playing, or use the widget.
|
||||
* Android 4.1 build: gapless only into a track whose file is already on the phone; FLAC is still transcoded
|
||||
(ExoPlayer has no FLAC decoder on Android 4.1).
|
||||
Reference in new issue
Block a user