Files
mesh-configs/skills/devops/mobile-apk-flutter-build/SKILL.md
T

127 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: mobile-apk-flutter-build
description: "Flutter-APK auf headless VPS bauen: Setup + AGP-Pitfalls."
version: 1.0.0
author: mehlzoerwer
platforms: [linux]
---
# Mobile APK bauen (Flutter, headless Linux-VPS)
Klasse: Eine Flutter-App als Android-APK auf einem headless Linux-VPS bauen und zum Download bereitstellen. Verifiziert 2026-08-07 für PersoEnt (VPS netcup, Ubuntu 24.04).
Hardware-Notiz: `flutter doctor` meldet "Android Studio not installed" und fehlendes Chrome/Linux-Toolchain — **beide sind für APK-Build nicht nötig**. Android toolchain ✓ reicht.
## 1. Flutter SDK installieren
```bash
cd /opt
curl -sL -o /tmp/flutter.tar.xz "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.24.5-stable.tar.xz"
tar xf /tmp/flutter.tar.xz # → /opt/flutter
echo 'export PATH="$PATH:/opt/flutter/bin"' >> /root/.bashrc
export PATH="$PATH:/opt/flutter/bin"
flutter --version # prüft Dart-Version (3.5.x)
```
## 2. 🔥 git safe.directory — DER "0.0.0-unknown"-Fix (PITFALL)
Wenn `flutter --version` / `flutter pub` meldet **"Flutter SDK version 0.0.0-unknown"** oder `fatal: detected dubious ownership in repository at '/opt/flutter'`, dann ist Flutters git-Versionserkennung gebrochen. Fix:
```bash
git config --global --add safe.directory /opt/flutter
```
Ohne diesen Schritt schlägt **jeder** `pub get` an Flutters eigener Versionsprüfung fehl ("The current Flutter SDK version is 0.0.0-unknown ... version solving failed"). Das ist NICHT ein echtes Versionsproblem — nur ownership. Nach dem Fix zeigt `flutter --version` wieder `3.24.5 • stable`.
## 3. Android SDK + Java
```bash
apt-get install -y openjdk-17-jdk unzip
# cmdline-tools:
mkdir -p /opt/android-sdk/cmdline-tools
curl -sL -o /tmp/cmdtools.zip "https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip"
unzip -q cmdtools.zip -d /opt/android-sdk/cmdline-tools/
mv /opt/android-sdk/cmdline-tools/cmdline-tools /opt/android-sdk/cmdline-tools/latest # 'latest' zwingend!
export ANDROID_HOME=/opt/android-sdk
export PATH="$PATH:/opt/android-sdk/cmdline-tools/latest/bin"
yes | sdkmanager --licenses
sdkmanager "platforms;android-34" "build-tools;34.0.0" "platform-tools"
```
Gradle lädt fehlende Build-Tools (z.B. 33.0.1) automatisch nach. Android-Studio NICHT nötig.
## 4. Projekt anlegen + Dependencies
```bash
flutter create --platforms=android --org de.persoent --project-name persoent_app persoent_app
cd persoent_app
```
Statt manuelle Versionen in pubspec zu erraten → `flutter pub add <pkg>` (löst passende Version selbst, inkl. `:^0.0.0` bei 0.x-Paketen):
```bash
flutter pub add pocketbase google_sign_in http shared_preferences
```
## 5. 🔥 AGP `namespace`-Konflikt mit älteren Plugins (PITFALL)
Symptom: `flutter build apk` → *"Could not create ... LibraryVariantBuilderImpl. > Namespace not specified. Specify a namespace in the module's build file."* (im Plugin, z.B. `:health_connect`).
Ursache: AGP 8.1 (im Projekt, `android/settings.gradle`) **erzwingt `namespace`**, aber ältere Plugin-Pakete (z.B. `health_connect ^0.x`) haben keinen. Optionen:
- **Einfachster robuster Weg:** das brechende Plugin `flutter pub remove <pkg>` **vorerst entfernen**, das Grundgerüst (Login+Dashboard) bauen → **erst funktionierendes APK, dann Health-Integration gezielt lösen**.
- Oder AGP 8.1 → 7.3 zurückstufen (matcht Flutters Gradle), riskant.
**Bau-Strategie (empfohlen):** erst minimales APK, das kompiliert; native Plugins (Health Connect usw.) danach einzeln, um Fehlerursachen zu isolieren.
## 5b. 🔥 `health_connect` auf pub.dev ist ein LEERES 0.0.0-Paket (PITFALL)
Symptom: `flutter pub add health_connect` liefert `health_connect-0.0.0` (im `~/.pub-cache/.../health_connect-0.0.0` nur ein leeres Verzeichnis), und der Build bricht mit dem AGP-`namespace`-Fehler.
Fakt: **Es existiert KEIN offizielles, funktionsfähiges `health_connect`-Flutter-Paket auf pub.dev.** Googles Health-Connect-Integration ist ein **GitHub-Beispiel**, das das Android-SDK nativ bundelt — nicht als veröffentlichtes pub-Paket gepflegt. `health_connect`/`health_connect_android` auf pub.dev sind leere Platzhalter.
Konsequenz für PersoEnt: Google-Gesundheitsdaten sind NICHT über ein magisches pub.dev-Paket abrufbar. Der echte Weg erfordert nativen Android-Health-Connect-Code (SDK-Binding) — das skizzierte der Nutzer als langfristige "PersoEnt als App"-Entscheidung; vorerst liefert die APK Login+Dashboard, Health-Import ist separat zu bauen. Siehe auch `references/persoent-google-health-strategy.md` (Google-Fit-REST deprecated, Health Connect nur Android-nativ, kein Server-REST-Sync).
## 6. Gate + Build
```bash
flutter analyze # vorher: fängt unbenutzte Imports / falsche Klassennamen
flutter build apk --release
```
- APK: `build/app/outputs/flutter-apk/app-release.apk` (~22MB)
- Erster Gradle-Build dauert lange (Downloads). Nutze langen Timeout.
- `test/widget_test.dart` muss zum neuen Code passen (Default referenziert `MyApp`).
## 7. Zum Download bereitstellen (VPS)
```bash
mkdir -p /var/www/<projekt>/html/app
cp build/app/outputs/flutter-apk/app-release.apk /var/www/<projekt>/html/app/<Name>-Android.apk
chown -R www-data:www-data /var/www/<projekt>/html/app/
# Test:
curl -s -o /dev/null -w "%{http_code}" "https://<domain>/app/<Name>-Android.apk" # 200
```
## 8. 🔥 Google-Sign-In Fehlercode 10 (PITFALL)
Symptom in der App (Nutzerscreenshot): `PlatformException(sign_in_failed, [google_sign_in] 10: null, null)`. Fehlercode **10 = OAuth-Client-Konfiguration fehlt/unverifiziert**:
- Dem Google-Cloud-Projekt fehlt der **Android-OAuth-Client**, oder
- der **SHA-1-Fingerprint** der App ist dort nicht hinterlegt.
Fix (Nutzer-Einbindung nötig, nur deren Konto kann das):
1. SHA-1 aus der gebauten APK extrahieren und eintragen:
```bash
keytool -printcert -jarfile app-release.apk | grep SHA1
```
2. Google-Cloud → Credentials → OAuth-Client "Android" mit diesem SHA-1 anlegen.
3. Die generierte **Client-ID** in `android/app/src/main/AndroidManifest.xml` als `<meta-data android:name="com.google.android.gms.auth.API_KEY" .../>`-Block eintragen, APK neu bauen.
## 9. 📸 Nutzer-Screenshots auswerten (Handy-Foto) ohne vision-Tool
Wenn der Nutzer einen Screenshot schickt und **kein vision_analyze-Tool** verfügbar ist, lässt sich der Text (Fehlermeldungen) per **Tesseract-OCR** auslesen:
```bash
tesseract /root/.hermes/cache/images/<img>.jpg - 2>/dev/null # Text auf stdout
```
Weg: `browser_get_images` liefert keine lokalen Dateien → stattdessen `file <pfad>` (Maße bestätigen) + `tesseract` zum Extrahieren von Fehlertext. Liefert z.B. `PlatformException(...)`-Zeilen — genug, um die Diagnose (Code 10, etc.) zu stellen. Hinweis: tesseract ist auf Ubuntu oft vorinstalliert (`/usr/bin/tesseract`).
## Referenzen
- `references/persoent-apk-2026-08-07.md` — Session-Transcript: voller Verlauf, Versionen, Fehlerbilder
- `references/persoent-google-health-strategy.md` — PersoEnt: Google-Gesundheitsdaten-Strategie (Fit-REST deprecated, Health-Connect nur nativ; Detektiv-Korrelations-Analytik)
- `references/persoent-cost-tracking.md` — **PersoEnt/Mesh-Kosten-Tracking + Budget-BREMSE (OpenRouter)**: mesh-cost-track.sh (stündlich, je Agent) + mesh-cost-break.py (kill_switches bei Deckel) + Agent-Poller-Guard (PAUSED → keine Task-Übernahme), E2E-getestet. PITFALLs: DREI OpenRouter-Kostenquellen unterscheiden (`/auth/key usage`≠Credits, `/credits total_usage`=USD verbindlich, Body-`usage.cost`); Usage KUMULATIV → **tag-übergreifendes Delta** (letzter-heute − letzter-gestern, max(0,·) gegen Reset), sonst endlos PAUSED; DeepSeek V4 Pro = 64% (Bremsen auf Modell-Ebene via `hermes config set model.providers.openrouter.blocked_models`, Singular `model.`); Master-exempt von PAUSED. **FINALER NUTZER-COST-MODEL (ab 08-08 ersetzt Monats-Cap): 1$/Tag/Agent hart, solange Credits da, KEIN Team-Monats-Stopp, Guthaben-0→Stopp.**
- `references/hermes-config-ops.md` — **Hermes-System-Operation (VPS/Master)**: Config NIE via patch — immer `hermes config set`; `approvals.mode=auto` (allowlist bleibt hart); **BACKUP-ONLY-Regel** (`.bak` vor jeder Änderung → keine extra Freigabe); Memory-Limits (4400/2750, verdoppelt); **„Wir, nicht du" Team-Pflicht** bei Kernsystemen.