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>
175 lines
8.9 KiB
Markdown
175 lines
8.9 KiB
Markdown
# 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. → ARIA bedient Apps (E-Mail-Setup).
|
||
4. **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`).
|
||
|
||
```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 (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.
|