Ehrlicher Bau-Weg (nur Docker noetig, dist/aria-android-agent.apk, Debug-Key, Installieren, Erst-Build-Kosten/Stolperer). release.sh klar als M4 geplant markiert statt als vorhandener Befehl. versionCode 2 / versionName 0.2.0 (M1+M2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
8.9 KiB
ARIA Android-Agent
Ein nativer Android-Agent (eigene APK), der ARIA erlaubt, ein Smartphone
fernzusteuern — inkl. Bedienen fremder App-UIs (z.B. „ARIA, richte auf dem
Handy ein E-Mail-Konto ein"). Gegenstück zum Desktop-host-agent (Linux/macOS/
Windows), aber Android ist kein Unix-Shell-System — deshalb ein anderes
Action-Set (UI-Automation statt beliebiger Shell-Kommandos).
Verbindet sich wie die ARIA-App ausgehend zum RVS (gleicher Token/Raum),
Verbindungs-Setup per QR-Scan oder manueller Eingabe. Taucht in der
Diagnostic unter Satelliten → Host-Agenten 💻 auf (host_hello mit
os="Android …" + Android-Caps).
Warum nativ (Kotlin), nicht Termux/RN
- UI-Automation (fremde Apps bedienen) geht auf Android nur über einen AccessibilityService — den kann nur eine native App bereitstellen.
- Screenshots einer laufenden Session: MediaProjection (native).
- Dauerbetrieb: Foreground-Service mit Notification (native).
- Termux gäbe nur Shell +
termux-api(SMS/Anruf/Standort …), kein Bedienen anderer App-UIs. Für „E-Mail-Konto durchklicken" reicht das nicht.
Tech: Kotlin, OkHttp-WebSocket (RVS-Client), CameraX/ML-Kit (QR), AccessibilityService (Input), MediaProjection (Screenshot). Build via Docker (Android-SDK + Gradle) → APK. Nur Linux baut APKs (Docker), Deploy manuell.
Action-Set (host_command → host_result)
Android-spezifisch (statt exec/read/write des Desktop-Agents):
| Action | Was |
|---|---|
screenshot |
Bildschirmfoto (MediaProjection) — ARIA sieht den Schirm |
ui_dump |
Sichtbare UI als Baum (Texte, Buttons, Felder + Koordinaten) — ARIAs „Augen" für gezieltes Tippen |
ui_tap |
Tippen (x,y ODER auf ein Element aus ui_dump) |
ui_text |
Text in das fokussierte/angegebene Feld schreiben |
ui_swipe |
Wischen/Scrollen |
ui_key |
Systemtasten (BACK, HOME, ENTER …) |
app_launch |
App per Paketname starten (z.B. E-Mail-App) |
app_list |
installierte Apps auflisten |
info |
Gerät: Modell, Android-Version, Akku, Netz, IP |
notify |
Benachrichtigung anzeigen |
| (später) | sms_send, call, location, clipboard (je nach Bedarf + Berechtigung) |
ARIA-Flow „E-Mail einrichten": app_launch (Mail-App) → screenshot/ui_dump
(sehen, was da ist) → ui_tap/ui_text (durchklicken) → wieder ui_dump prüfen,
bis fertig. Genau das agentische Muster wie beim Endian-Fix, nur mit Handy-UI.
Dauerbetrieb — Foreground-Service vs. Push (FCM)
Der Agent muss immer erreichbar sein, obwohl Android Hintergrundprozesse aggressiv killt (Doze, App-Standby, OEM-Batterie-Manager wie Xiaomi/Huawei). Zwei Wege, deine WhatsApp-Intuition trifft ins Schwarze:
A) Foreground-Service (persistente WebSocket) — der einfache Start:
- Dauerhafte RVS-Verbindung + Foreground-Notification („Agent aktiv").
- Braucht:
FOREGROUND_SERVICE, Akku-Optimierung ausnehmen (REQUEST_IGNORE_BATTERY_OPTIMIZATIONS— User whitelistet die App),RECEIVE_BOOT_COMPLETED+ BootReceiver (Neustart nach Reboot), Auto-Reconnect (haben wir im Protokoll schon). - Reutzt unser bestehendes
host_hello/host_command/host_result1:1. - Nachteil: etwas Akku; manche OEMs killen trotzdem → „Autostart" manuell erlauben.
B) Self-hosted Push (KEIN Google!) — genau wie WhatsApp, aber auf eigenem Server:
- UnifiedPush + self-hosted ntfy: Auf dem ARIA-Server läuft ntfy (freier, self-hostbarer Push-Server). Der Agent nutzt UnifiedPush (offener Standard, de-Google-Welt/F-Droid) mit dem ntfy-Distributor auf dem Handy. Will ARIA etwas, POSTet die Bridge/RVS an ntfy → weckt die App → sie holt den Befehl vom RVS, arbeitet, antwortet. Läuft auch auf Custom-ROMs OHNE Google Play Services.
- Akkuschonend wie FCM, aber ohne jede Google-Abhängigkeit. Nur ein Dienst mehr (ntfy) im Stack + der Push-Auslöser serverseitig.
C) FCM (Google) — optional: Wer ein Stock-Android mit Play Services hat und Googles Push-Kanal will, kann FCM statt ntfy nehmen (bester Akku auf GMS-Geräten). Braucht Firebase-Projekt + Play Services. Nur eine Option, keine Pflicht.
Custom-ROM ohne Google: → Weg A (eigener Socket) oder B (self-hosted ntfy). Beide brauchen KEIN Google. Für Stefans dediziertes Ziel-Handy ist A sogar oft die einfachste Dauerlösung (unser eigener „Push" über den RVS-Socket).
Hybrid (ideal, End-Ausbau): Im Leerlauf nur Push (max. Akku). Ein Push weckt die App → sie öffnet die RVS-Verbindung, hält sich per Wakelock für die Interaktion wach (mehrere Befehle flüssig, z.B. E-Mail-Setup durchklicken) → schläft nach ein paar Sekunden Ruhe wieder ein. So WhatsApp-Akku UND schnelle Multi-Befehl-Sessions. Der Push kommt dabei von B (self-hosted ntfy) oder C (FCM) — freie Wahl. Erste Push-Latenz aus tiefem Doze ~1–3 s; danach bleibt der Socket die Session offen.
Empfehlung: Meilenstein 1–3 mit A (Foreground-Service) — läuft sofort und nutzt alles Vorhandene, damit wir schnell einen funktionierenden Agenten haben, ganz ohne externe Dienste. Dann Push-Hybrid mit self-hosted ntfy (B) als Akku-Ausbau — KEIN Google. FCM (C) nur optional für Stock-Android. Action-Set/Protokoll bleiben identisch, nur der Wecker ändert sich.
Sicherheit
- Reagiert nur auf den eigenen RVS-Raum (Token); Setup per QR/manuell.
- CONTROL_ENABLED-Schalter in der App (Default AUS) — erst wenn Stefan es bewusst aktiviert, führt der Agent Aktionen aus.
- AccessibilityService + MediaProjection müssen vom User explizit in den Android-Einstellungen freigegeben werden (kein stiller Zugriff möglich).
- Alle Aktionen werden protokolliert (In-App-Log + optional an ARIA).
- Voller Gerätezugriff — nur auf eigenen/anvertrauten Geräten nutzen.
Meilensteine
- ✅ Verbinden + sichtbar — Gradle-Projekt, AndroidManifest, RVS-WS-Client,
Foreground-Service, Connect-UI (QR-Scan + manuell),
host_hello/host_ping. → Agent erscheint in der Diagnostic.infofunktioniert. - ✅ Sehen — MediaProjection-Screenshot (
ScreenCapturer, gleicher{format,bytes,base64}-Vertrag wie der Desktop-Agent →host_screenshot) +ui_dump(AriaAccessibilityService, nur lesend → Brain-Toolhost_ui_dump). Freigabe einmalig in der App: „Bildschirm-Zugriff erlauben" + „Bedienungshilfe öffnen". → ARIA sieht den Schirm und liest die UI-Elemente mit Koordinaten. - Steuern —
ui_tap/ui_text/ui_swipe/ui_key/app_launchüber den AccessibilityService. → ARIA bedient Apps (E-Mail-Setup). - Feinschliff —
info/app_list/notify, Build-Härtung,release.sh(Version-Param → Gitea-Release-Asset, wie die App).
Bauen
APK-Builds laufen nur unter Linux — deshalb im Docker-Container. Du brauchst
nichts Android-spezifisches installiert, nur Docker. Android-SDK, Gradle und
Build-Tools zieht der Container selbst (Dockerfile.build).
cd host-agent/android
./build.sh
build.sh baut das Image aria-android-agent-build und lässt darin
gradle assembleDebug laufen. Ergebnis:
host-agent/android/dist/aria-android-agent.apk
Das ist ein Debug-APK: auto-signiert mit dem Android-Debug-Key, also direkt installierbar — ohne eigenen Keystore, ohne Play Store.
Auf dem Handy installieren
dist/aria-android-agent.apkaufs Zielgerät kopieren (USB, Cloud,adb install dist/aria-android-agent.apk, …).- Antippen → Android fragt nach „Unbekannte Quellen / Aus dieser Quelle installieren erlauben" → erlauben.
- App öffnen → verbinden (QR/manuell), „Steuerung erlauben" an, für M2 zusätzlich „Bildschirm-Zugriff erlauben" + „Bedienungshilfe öffnen".
Was der erste Build kostet
Der erste Lauf lädt viel (JDK-Image, Gradle, Android-SDK, Dependencies) und dauert entsprechend — mehrere Minuten. Folge-Builds sind schnell (Docker-Layer + Gradle-Cache im Image). Häufige Stolperer:
- Docker fehlt / kein Zugriff →
docker-Rechte prüfen (docker ps). - Overlay-on-Overlay auf einem Live-ISO („invalid argument" beim Image-Bau) — gleiches Problem wie beim Desktop-Agent auf dem Mint-Live-System; von einer installierten Linux-Kiste bauen.
- Kotlin-/Manifest-Fehler beim allerersten Bau eines neuen Meilensteins: den Gradle-Fehler posten, das glätten wir schnell.
Version setzen
Bis es release.sh gibt, wird die Version in app/build.gradle gepflegt
(versionCode / versionName). Aktuell 1 / 0.2.0 (M1+M2).
Release (geplant — Meilenstein 4)
release.sh <version> — wie die release.sh der Haupt-App: nimmt die
Versionsnummer als Parameter, baut das APK, taggt und lädt es als
Gitea-Release-Asset hoch, damit der Download einfach ist. Noch nicht gebaut.
Status: M1 + M2 fertig (verbinden,
info,screenshot,ui_dump). Als Nächstes Meilenstein 3 (Steuern), Release-Skript in M4.