diff --git a/.gitignore b/.gitignore index e972d75..9bd7b58 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ spike/*.m4a # nicht ins Repo rutscht, wenn jemand die Datei woandershin legt. bridge-token +# Heruntergeladene Termux-APKs (Zwischenspeicher von install-termux.sh) +provision/apk-cache/ + # Python-Bytecode (entsteht beim Ausführen von bridge-mini.py) __pycache__/ *.py[cod] diff --git a/README.md b/README.md index d380ab4..4cc13f3 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ Getestet wird auf einem **OnePlus 7 Pro (Snapdragon 855, Adreno 640) mit Stock O ```bash # 1. Auf dem PC. Verbindet per USB oder WLAN — das Skript fragt danach. # Ein Kabel wird nicht gebraucht: Android 11+ kann Wireless Debugging. +# Fehlt Termux, bietet es an, alle vier Apps herunterzuladen und +# fernzuinstallieren (oder direkt: ./provision/install-termux.sh). ./provision/provision.sh # 2. Auf dem Telefon in Termux: diff --git a/provision/install-termux.sh b/provision/install-termux.sh new file mode 100755 index 0000000..e182572 --- /dev/null +++ b/provision/install-termux.sh @@ -0,0 +1,197 @@ +#!/usr/bin/env bash +# HPOS — Termux samt Zusatz-Apps installieren, alles aus einer Quelle. +# +# Termux und seine Plugins teilen sich eine Android-UID (sharedUserId=com.termux). +# Android verlangt, dass Apps mit gemeinsamer UID mit DEMSELBEN Schlüssel signiert +# sind. F-Droid und GitHub signieren verschieden — mischt man beide, scheitert die +# Installation mit INSTALL_FAILED_SHARED_USER_INCOMPATIBLE. Das ist der mit Abstand +# häufigste Stolperstein beim Einrichten und der Grund, warum es dieses Skript gibt. +# +# Gewählt wird GitHub, aus zwei Gründen: +# · Termux:X11 gibt es dort in einer sharedUid-Variante. Die läuft in Termux' +# Prozessgruppe und erbt damit die Akku-Ausnahmen, die provision.sh setzt. +# Die normale Variante ist eine eigenständige Hintergrund-App, die Android +# drosselt — bei ROMs wie ColorOS ein spürbarer Unterschied. +# · Eine Quelle, ein Schlüssel, keine Mischmasch-Fehler. +# +# Aufruf: ./provision/install-termux.sh +set -uo pipefail +source "$(dirname "$0")/lib.sh" + +CACHE="$(cd "$(dirname "$0")" && pwd)/apk-cache" +mkdir -p "$CACHE" + +# Paket → GitHub-Repo → Muster (Rangfolge, Komma-getrennt) → Beschreibung +# +# Reihenfolge der Einträge zählt: die Haupt-App muss zuerst installiert werden, +# sonst findet der Plugin-Install keine gemeinsame UID vor. +# +# Bei termux-app gibt es mehrere Varianten je Release. 'apt-android-7' ist die +# heutige Fassung für Android 7 und neuer; 'apt-android-5' ist der Altbau für +# ältere Geräte und würde auf einem aktuellen Telefon unnötig zurückfallen. +# Deshalb eine Rangfolge statt eines einzelnen Musters. +APPS=( + "com.termux|termux/termux-app|apt-android-7-github-debug_universal.apk,_universal.apk|Termux (Haupt-App)" + "com.termux.api|termux/termux-api|.apk|Termux:API (Sensoren, Mikrofon, Taschenlampe)" + "com.termux.boot|termux/termux-boot|.apk|Termux:Boot (Autostart nach Neustart)" + "com.termux.x11|termux/termux-x11|universal-sharedUid-debug.apk|Termux:X11 (Grafikausgabe)" +) + +kopf "Werkzeug" +adb_einrichten || true +hinweis "adb $(adb_version "$ADB_BIN")" + +if ! geraet_waehlen; then + fehl "Kein Gerät verbunden." + hinweis "Erst verbinden: ./provision/adb-wireless.sh (oder Kabel anschließen)" + exit 1 +fi +ok "Gerät: ${ADB_SERIAL} ($(geraet_beschreiben "$ADB_SERIAL"))" + +# ── Bestandsaufnahme ───────────────────────────────────────────────────────── +# Was schon da ist, stammt möglicherweise aus einer anderen Quelle. Von außen +# lässt sich das nicht zuverlässig unterscheiden, deshalb wird gefragt statt geraten. +kopf "Vorhandene Termux-Apps" +VORHANDEN=() +while IFS= read -r p; do + [ -n "$p" ] && VORHANDEN+=("$p") +done < <(adb shell pm list packages 2>/dev/null | tr -d '\r' | sed 's/^package://' | grep -E '^com\.termux' || true) + +if [ ${#VORHANDEN[@]} -eq 0 ]; then + ok "Nichts vorinstalliert — sauberer Start." +else + for p in "${VORHANDEN[@]}"; do printf ' %s\n' "$p"; done + cat <<'TEXT' + + Diese Apps sind bereits installiert. Stammen sie aus einer anderen Quelle + (etwa F-Droid), scheitert jede weitere Installation von GitHub an den + unterschiedlichen Signaturen. + + ACHTUNG: Deinstallieren löscht auch das Termux-Dateisystem und damit ein + eventuell vorhandenes Linux-Rootfs. Vor einer bestehenden HPOS-Installation + unbedingt vorher ein Backup ziehen. +TEXT + printf '\n Vorhandene Termux-Apps deinstallieren? [j/N] > ' + read -r WEG /dev/null 2>&1; then ok "entfernt: $p" + else warn "konnte $p nicht entfernen"; fi + done + ;; + *) + hinweis "Behalten. Falls die Installation gleich scheitert, ist das der Grund." + ;; + esac +fi + +# ── Herunterladen ──────────────────────────────────────────────────────────── +asset_url() { + local repo="$1" muster="$2" + curl -sfL "https://api.github.com/repos/$repo/releases" \ + | python3 -c ' +import json, sys + +muster = [m for m in sys.argv[1].split(",") if m] +try: + releases = json.load(sys.stdin) +except Exception: + sys.exit(1) + +def suche(kandidaten): + """Erstes Muster gewinnt, erst dann wird das nächste Release betrachtet — + sonst nähme man aus einem älteren Release die bevorzugte Variante statt aus + dem neueren die zweitbeste.""" + for r in kandidaten: + for m in muster: + for a in r.get("assets", []): + if a["name"].endswith(m): + return a["browser_download_url"] + return None + +# Stabile Veröffentlichungen zuerst, Vorabversionen nur als Rückfallebene. +# Termux:X11 erscheint ausschließlich als "nightly", ist dort aber nicht als +# prerelease markiert und wird deshalb schon im ersten Durchgang gefunden. +stabil = [r for r in releases if not r.get("prerelease")] +vorab = [r for r in releases if r.get("prerelease")] + +url = suche(stabil) or suche(vorab) +if not url: + sys.exit(1) +print(url) +' "$muster" +} + +kopf "Herunterladen" +DATEIEN=() +for eintrag in "${APPS[@]}"; do + IFS='|' read -r paket repo muster beschreibung <<<"$eintrag" + printf ' %s\n' "$beschreibung" + URL=$(asset_url "$repo" "$muster") + if [ -z "$URL" ]; then + fehl "Kein passendes Release-Asset gefunden ($repo, Muster: $muster)" + hinweis "Releases von Hand prüfen: https://github.com/$repo/releases" + exit 1 + fi + DATEI="$CACHE/$(basename "$URL")" + if [ -s "$DATEI" ]; then + ok "bereits im Zwischenspeicher: $(basename "$DATEI")" + else + if curl -fL --progress-bar -o "$DATEI.teil" "$URL" && mv "$DATEI.teil" "$DATEI"; then + ok "geladen: $(basename "$DATEI")" + else + rm -f "$DATEI.teil" + fehl "Download fehlgeschlagen: $URL" + exit 1 + fi + fi + DATEIEN+=("$paket|$DATEI|$beschreibung") +done + +# ── Installieren ───────────────────────────────────────────────────────────── +# Reihenfolge wie in APPS: Haupt-App zuerst, dann die Plugins. +kopf "Installieren" +FEHLER=0 +for eintrag in "${DATEIEN[@]}"; do + IFS='|' read -r paket datei beschreibung <<<"$eintrag" + printf ' %s … ' "$beschreibung" + AUS=$(adb install -r -g "$datei" 2>&1) + if printf '%s' "$AUS" | grep -qi 'success'; then + printf '%s✓%s\n' "$C_OK" "$C_OFF" + else + printf '%s✗%s\n' "$C_ERR" "$C_OFF" + printf '%s' "$AUS" | tail -3 | sed 's/^/ /' + FEHLER=1 + case "$AUS" in + *SHARED_USER_INCOMPATIBLE*|*签名*|*signatures*) + hinweis "Genau der Signaturkonflikt: es ist noch eine Termux-App aus einer" + hinweis "anderen Quelle installiert. Skript erneut aufrufen und beim" + hinweis "Deinstallieren mit 'j' antworten." + ;; + esac + fi +done + +# ── Abschluss ──────────────────────────────────────────────────────────────── +kopf "Ergebnis" +adb shell pm list packages 2>/dev/null | tr -d '\r' | grep -E '^package:com\.termux' | sed 's/^package:/ /' + +if [ "$FEHLER" = 0 ]; then + ok "Alle vier Apps installiert, alle aus derselben Quelle." + cat <<'TEXT' + + Nächste Schritte: + + 1. Termux einmal öffnen, damit es sein Dateisystem anlegt. + 2. ./provision/provision.sh — Akku- und Hintergrundeinstellungen + 3. Auf dem Telefon: bash spike/00-bootstrap-termux.sh + + Termux:X11 ist die sharedUid-Variante: sie läuft in Termux' Prozessgruppe und + erbt dessen Akku-Ausnahmen. Das ist bei ROMs, die Hintergrund-Apps aggressiv + beenden, der Unterschied zwischen "läuft über Nacht" und "war morgens weg". +TEXT +else + warn "Nicht alles hat geklappt — siehe oben." + exit 1 +fi diff --git a/provision/provision.sh b/provision/provision.sh index 08720e1..859b21b 100755 --- a/provision/provision.sh +++ b/provision/provision.sh @@ -159,21 +159,37 @@ else Auf dem Telefon einfach im Browser öffnen und die APK installieren. "Installation aus unbekannten Quellen" muss für den Browser erlaubt sein. TEXT - if [ "$TROCKEN" != 1 ]; then - printf '\n Soll ich die Termux-Seite auf dem Telefon öffnen? [J/n] > ' - read -r OEFFNEN ' + read -r AUTOINSTALL /dev/null 2>&1 \ - && ok "Seite auf dem Telefon geöffnet" \ - || warn "Konnte den Browser nicht starten — bitte von Hand aufrufen." + if ADB_SERIAL="$ADB_SERIAL" "$HIER/install-termux.sh"; then + ok "Termux ist installiert — weiter mit der Einrichtung." + hinweis "Bitte Termux einmal öffnen, damit es sein Dateisystem anlegt." + printf ' Wenn das erledigt ist, Enter drücken > ' + read -r _