Defects. "Kopplung zurücksetzen" now asks first, naming how many phones would have to scan again — one stray OK used to wipe a working pairing, and the settings put the focus right on it: entering the screen landed on the gear, one press down jumped into the right column onto that very action, and every further press down did nothing. Focus now starts on the first row of the left column. 1. FC Köln was labelled "EFC". An unreachable source used to look like an evening without programmes — cached list, empty EPG, club menus counting down to zero — so both repositories now record when they last came through, and the top bar says "Server nicht erreichbar · Stand 14:46". The field labels on "Erweitert" sat on the outline with the border running through them; they sit above their field now. Polish. The app opens on the channel list — on the channel last watched, which survives a restart — instead of the settings gear. Rows without EPG fill their empty half with the channel's group. The club chip says "ab 15:06" like the row next to it, the club menu carries the club's name instead of "FCSP", and a fixture title is shortened to the fixture, so "Pokal: Nordstadt - FC St. P…" became "Nordstadt - FC St. Pauli". The settings are three columns and no longer scroll (CONTEXT.md's ten-foot rule). Features. Favourites work for a plain M3U source too, stored on the device and mirrored to the phone; they used to exist only with a Dispatcharr login. The channel keys jump the list by initial letter, left and right jump a division in the club picker, and right on a channel opens its day plan — the EPG beyond now/next, which was parsed all along and never shown. When a club match starts elsewhere the player offers to switch. The remote asked for a code "unten auf dem TV-Bildschirm" where none was; the welcome screen shows it now and the wording points at where it is. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Castarr
Live-TV auf dem Fernseher, eingerichtet in einer Minute — alles läuft übers Handy.
Castarr ist eine App für Google TV / Android TV. Auf dem Fernseher muss nie etwas getippt werden: Zum Einrichten scannt man einmal einen QR-Code mit dem Handy, meldet sich dort an — fertig. Danach zappt man mit der normalen TV-Fernbedienung oder steuert alles bequem vom Handy aus.
| Senderliste | Player |
|---|---|
![]() |
![]() |
| Nummerntasten | Einrichtung |
|---|---|
![]() |
![]() |
Was die App kann
- Senderliste mit Logos und Programm — was gerade läuft, wie lange noch, was danach kommt. Gruppen und Favoriten links, Sender rechts.
- Zappen wie früher — Nummerntasten auf der Fernbedienung schalten direkt um (mit großer Anzeige, welcher Sender gleich kommt), hoch/runter blättert durch die Sender.
- Aufgeräumter Player — OK-Taste zeigt Sendung, Zeiten und Fortschritt, dazu Pause/Stopp-Buttons und Tonspur-Wahl, wenn der Sender mehrere hat. Blendet sich von selbst wieder aus.
- Handy als Fernbedienung — QR-Code in den Einstellungen scannen, schon hat man Senderliste, Suche, Lautstärke und Favoriten im Handy-Browser. Keine App-Installation nötig.
- Favoriten — OK auf einem Sender gedrückt halten, Stern gesetzt. Die Favoriten gelten pro Person und sind auf jedem Gerät dieselben.
- Updates aus der App heraus — unter Einstellungen → App genügt ein Klick, wenn eine neue Version bereitsteht.
Installation auf dem Fernseher
- Auf dem Google TV die App Downloader installieren (oder einen anderen Weg nutzen, eine APK-Datei zu öffnen).
- Diese Adresse eingeben:
git.beckm4nn.net/be-nj/castarr/raw/branch/apk/castarr.apk - Installation bestätigen („Unbekannte Quellen" für Downloader erlauben, wenn der Fernseher fragt).
- Castarr starten und den drei Schritten auf dem Bildschirm folgen: QR-Code scannen, auf dem Handy Server angeben und anmelden — den Rest macht der Fernseher.
Danach hält sich die App über den eingebauten Updater selbst aktuell.
Für Technikinteressierte
Native Kotlin-App (Jetpack Compose for TV, Media3/ExoPlayer für HLS und MPEG-TS). Als Backend dient ein Dispatcharr-Fork mit OIDC-Unterstützung: Anmeldung per Device Authorization Grant (der Fernseher zeigt QR + Code, bestätigt wird am Handy beim Identity Provider), API-Zugriff per Bearer-Token, Favoriten und Ausgabeprofile pro Nutzer. Ohne Dispatcharr funktioniert auch jede M3U-Playlist (+ optionales XMLTV) als generische Quelle — ErsatzTV, Threadfin, Tunarr, einfache Playlists.
Die Handy-Fernbedienung serviert der Fernseher selbst (eingebetteter HTTP/WebSocket-Server, Kopplung per QR-Token mit ratenlimitiertem Zahlencode als Fallback). Physische Mediatasten und Google Assistant funktionieren über eine Media3 MediaSession.
Selbst bauen
JDK 17+ und Android SDK (Platform 35) erforderlich; eine passende JDK-Toolchain wird automatisch aufgelöst (foojay).
./gradlew assembleDebug # Debug-APK
./gradlew assembleRelease # signiert, wenn CASTARR_STORE_*-Env gesetzt ist
APK-Ausgabe: app/build/outputs/apk/<variant>/. Die Releases hier im Repo
sind signiert; über einem Debug-Build muss einmal deinstalliert werden
(Signaturwechsel). Updates bezieht die App über die Release-API dieses
Repos, die APK selbst liegt auf dem Branch apk.
Tests
./gradlew test # Unit-Tests, Reports unter tests/runs/
tests/smoke.sh # Emulator: bauen, starten, durchklicken (~40 s)
tests/smoke.sh --stop # dasselbe, Emulator danach herunterfahren
tests/smoke.sh baut das Debug-APK, setzt die Demo-Playlist als Quelle,
läuft mit dem D-Pad von der Senderliste bis in den Player und schlägt fehl
bei Absturz, ANR oder leerer Senderliste. Screenshots und Log landen unter
tests/runs/. Nicht abgedeckt: echte Wiedergabe, Onboarding am Handy,
Kopplung.
Der Emulator dahinter lässt sich auch einzeln steuern:
tests/helpers/emulator.sh start | stop | status
tests/helpers/emulator.sh install <apk>
tests/helpers/emulator.sh shot <name>
Er startet aus einem Snapshot und ist in wenigen Sekunden oben; stop
schreibt den Snapshot vorher neu. Ein Kaltstart entsteht nur, wenn der
Snapshot fehlt (AVD castarr-googletv, API 34).
Release
tools/release.sh 0.11.6 --notes notes.md
Bumpt die Version, testet, baut signiert, taggt, schiebt die APK auf den
Branch apk und legt das Gitea-Release an. Ohne --notes schreibt es einen
Entwurf aus den Commit-Betreffs, den du selbst ausformulierst — Release-Notes
erfindet das Skript nicht.
Architektur-Notizen: CONTEXT.md und docs/adr/.



