#20 Each settings column is a focus group now. The middle column is shorter than the left, so "down" past its last row used to search wider and land back in the left column — "Erweitert" was only reachable by going right, down, left. #22 The whole backend path had no coverage, which is why an afternoon against the real instance found three bugs. Parsing moved out of DispatcharrRepository into DispatcharrJson and is covered by twelve tests built from the shapes that instance actually returns: pagination, channels without a uuid or hidden from output, effective vs plain names and logos, favourites without the key, inactive output profiles, and all three EPG envelopes the fork has shipped. Android's stub org.json throws in unit tests, so the real implementation is on the test classpath. What no test can reach is written down in tests/dispatcharr-checkliste.md. #24 The remote's channel tab was only ever read in source. Driven through the DevTools protocol against the real backend it lists 503 channels with logos and EPG, the search filters, the club chip switches view, and a star survives the round trip to the backend and back — set and unset. It also showed the phone still spelling out "BL: Bayer Leverkusen - VfB Stuttgart, tipico Topspiel der Woche, 16. Spieltag" where the TV shortens to the fixture; the payload shortens now too. #23 The TV says "Der alte Code war abgelaufen — neuer Code 566071643" instead of swapping the digits without a word. 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/.



