# 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_result` 1: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 1. **✅ Verbinden + sichtbar** — Gradle-Projekt, AndroidManifest, RVS-WS-Client, Foreground-Service, Connect-UI (QR-Scan + manuell), `host_hello`/`host_ping`. → Agent erscheint in der Diagnostic. `info` funktioniert. 2. **✅ Sehen** — MediaProjection-Screenshot (`ScreenCapturer`, gleicher `{format,bytes,base64}`-Vertrag wie der Desktop-Agent → `host_screenshot`) + `ui_dump` (`AriaAccessibilityService`, nur lesend → Brain-Tool `host_ui_dump`). Freigabe einmalig in der App: „Bildschirm-Zugriff erlauben" + „Bedienungshilfe öffnen". → ARIA sieht den Schirm und liest die UI-Elemente mit Koordinaten. 3. **✅ Steuern** — `ui_tap`/`ui_text`/`ui_swipe`/`ui_key`/`app_launch` über den AccessibilityService (`canPerformGestures`, `dispatchGesture`, `ACTION_SET_TEXT`, `performGlobalAction`) → Brain-Tools `host_ui_tap`/`_text`/`_swipe`/`_key`/ `host_app_launch`. Tap-Koordinaten = die x/y aus `ui_dump` (echte Pixel), NICHT aus dem (skalierten) Screenshot. → ARIA bedient Apps (E-Mail-Setup). 4. **Feinschliff** — `app_list`/`notify`, Build-Härtung, `release_agent.sh`. ## 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`). ```bash 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 1. `dist/aria-android-agent.apk` aufs Zielgerät kopieren (USB, Cloud, `adb install dist/aria-android-agent.apk`, …). 2. Antippen → Android fragt nach **„Unbekannte Quellen / Aus dieser Quelle installieren erlauben"** → erlauben. 3. 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 Das APK ist **kein** Teil des Git-Trees (blaeht sonst die History dauerhaft auf) — es wird als **Release-Asset** an einen Tag gehaengt. Das macht `release_agent.sh` (liegt eine Ebene hoeher, in `host-agent/`): ```bash cd host-agent ./release_agent.sh 0.2.0 ``` Das Skript (wie die `release.sh` der Haupt-App, Version als Parameter): - setzt die Version (`host_agent.py` → `AGENT_VERSION`, `app/build.gradle` → `versionName`/`versionCode`), - baut **Linux-Binary + Android-APK** per Docker, - committet den Version-Bump, taggt **`agent-v`** (eigener Namespace, kollidiert nicht mit den App-Tags `v`) und pusht, - legt ein Gitea-Release an und laedt die Assets hoch: `aria-host-agent-linux-x64`, `aria-host-agent-android-agent-v.apk`, optional `-macos` / `-windows.exe` (falls in `host-agent/dist/` vorgebaut). Gitea-Zugang (`GITEA_URL`, `GITEA_REPO`, `GITEA_USER`) kommt aus der Umgebung oder einer `.env`; das Kennwort wird interaktiv abgefragt. **Binaries landen unter „Releases", nie im Tree.** > Status: **M1–M3 fertig** — verbinden, `info`, `screenshot`, `ui_dump` (sehen) > und `ui_tap`/`ui_text`/`ui_swipe`/`ui_key`/`app_launch` (steuern); > `release_agent.sh` vorhanden. Damit läuft der volle Ablauf sehen→steuern > (z.B. E-Mail-Konto einrichten). Nächstes: Feinschliff (M4).