Files
podlite/README.md
T
XoséandClaude Opus 5.5 a6d2c8b2d2 Backport from the iOS version: never mark early endings as played, stall warning, Close
- An episode only counts as played when playback reaches the last minute.
  Saved files that "complete" early (cut-short download, SD card problems) were
  marked as played on the server, as were streams ending 30-60 s early; now a
  stream is retried and a file is reported.
- "Playing" but the position not moving for 12 s: say so.
- Menu -> "Pechar MiniABS" (Latest/Shows/Saved and the player): save the
  position, stop playback and close the app.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 16:05:13 +02:00

6.3 KiB
Raw Blame History

MiniABS

A tiny Audiobookshelf podcast client for the Samsung Galaxy Mini (GT-S5570) and other Android 2.2+ phones. Native Java, no libraries, ~130 KB. The interface is in Galician, with large text and touch targets sized for the Mini's 240×320 screen. Its purple colour scheme and launcher icon come from the Audiobookshelf icon pack (art/icon_master_512.png); tools/make_icons.py derives the notification and player icons from it.

Install

  1. Copy MiniABS.apk to the phone (USB to the SD card, or download it in the browser).
  2. On the phone: Settings → Applications → Unknown sources → tick it.
  3. Open the APK from a file manager and install. It can be moved to the SD card (Settings → Applications → Manage applications → MiniABS → Move to SD card).

Connecting

At home, the simplest option is your server's local http:// address, e.g. http://192.168.1.10:13378.

Sign in with your username and password, or tick "Use an API key instead". It works with both current servers (2.26+, short-lived access tokens that MiniABS refreshes automatically) and older ones (single long-lived token).

HTTPS (from outside your home)

Android 2.3 only speaks TLS 1.0, which modern servers refuse. So HTTPS needs one change on the server and is handled by the app from there.

Server: a legacy HTTPS port

Add a second server block to nginx, on its own port, used only by the phone. Your normal HTTPS site stays strict.

server {
    listen 8443 ssl;
    server_name abs.example.com;
    ssl_certificate     /etc/letsencrypt/live/abs.example.com/fullchain.pem;  # must be an RSA certificate
    ssl_certificate_key /etc/letsencrypt/live/abs.example.com/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    # @SECLEVEL=0 is required: OpenSSL 3 refuses TLS 1.0 without it
    ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:AES128-SHA:@SECLEVEL=0";
    ssl_prefer_server_ciphers on;
    client_max_body_size 0;
    location / {
        proxy_pass http://127.0.0.1:13378;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_buffering off;
    }
}

Then sign in with https://abs.example.com:8443.

  • RSA certificate: Android 2.3 can't use ECDSA certificates. With certbot, request one with --key-type rsa.
  • Security: TLS 1.0 with these ciphers is weak by today's standards, but much better than plain HTTP over the internet. Only open this port if you need it.
  • Caddy can't serve TLS 1.0; put nginx (or HAProxy) in front for this port.

App: certificates

  • Built-in roots: MiniABS trusts what the phone trusts, plus modern root certificates the phone's 2011-era list lacks: Let's Encrypt, Google Trust Services, Sectigo/ZeroSSL, DigiCert G2, Amazon and others. Most certificates just work.
  • Anything else (self-signed, a private CA, a new root): MiniABS shows the certificate's SHA-256 fingerprint and asks once. Compare it with the fingerprint your computer's browser shows for the site before tapping Trust. It then trusts the CA that issued it, so renewals keep working.
  • Settings → Certificates you trusted lets you forget them.

App: streaming

Android 2.x's media player can't stream https:// URLs, so for HTTPS servers MiniABS runs a small proxy on the phone (127.0.0.1 only, random unguessable URLs). It forwards seeks and gets a fresh sign-in token for each request, so long episodes don't break when the token expires.

Using it

  • Latest: "Continue listening" plus the newest episodes across your podcast library. Tap the library name at the top to switch libraries.
  • Shows: every podcast; tap one for its episodes. Menu key → sort oldest/newest, hide played.
  • Saved: episodes downloaded to the SD card, plus download progress.
  • Tap an episode to play. Long-press for Download, Delete download, Mark as played/unplayed, Go to show.
  • Player: skip back/forward (set the amounts in Settings), seek bar, show notes. Menu key → sleep timer, mark as played, download, stop, close MiniABS.
  • Close: Menu key → Pechar MiniABS (on the Latest/Shows/Saved screen or the player) saves the position, stops playback and closes the app.
  • Headset buttons: play/pause; next/previous skip forward/back. Playback pauses when headphones are unplugged and during calls.

Colored dots: blue = new, amber = in progress (with a bar), grey = played.

Progress sync

Playback opens an Audiobookshelf session and syncs every 15 seconds and on pause, so progress follows you to other apps. An episode only counts as played when playback gets within a minute of its end: a stream that drops or a saved file cut short is retried or reported, never marked as played. If playback says it's playing but stops moving for 12 seconds, MiniABS says so. Saved episodes play offline; their positions are kept on the phone and sent to the server next time you're online (or tap refresh on the Saved tab).

Limits

  • Episodes are streamed with direct play. Formats Android 2.x can't decode (e.g. Opus) can't be played, since the transcoded HLS stream isn't supported on 2.x.
  • No playback speed control: Android 2.x's media player doesn't support it.
  • Downloads need an SD card. "Download on Wi-Fi only" is on by default.

Building

Needs a JDK, aapt, dalvik-exchange (dx), zipalign, apksigner (Ubuntu: apt install aapt dalvik-exchange zipalign apksigner) and an API 8 android.jar:

ANDROID_JAR=/path/to/android-8/android.jar ./build.sh

Compiling against the API 8 jar guarantees no newer Android APIs are used. The APK is signed with miniabs.keystore (password miniabs); keep it to install updates over the top.

All sizes (text, rows, buttons, covers) are in res/values/dimens.xml; change them there and rebuild.

tools/gen_roots.py regenerates the bundled root certificates from a system CA store.

test/run_tests.sh runs the API, JSON, progress, HTTPS-trust and streaming-proxy code on the desktop JVM against a mock Audiobookshelf server (test/mock_abs.py), over plain HTTP and over TLS with good, expired, wrong-host, forged and self-signed certificates (test/make_pki.sh).