install-termux.sh: APKs laden und fernzuinstallieren
Termux und seine Plugins teilen sich eine Android-UID (sharedUserId=com.termux). Android verlangt für Apps mit gemeinsamer UID denselben Signaturschlüssel — und F-Droid und GitHub signieren verschieden. Wer die Quellen mischt, scheitert an INSTALL_FAILED_SHARED_USER_INCOMPATIBLE, ohne dass die Meldung erklärt warum. Das Skript lädt alle vier Apps von GitHub und installiert sie über die bestehende adb-Verbindung, per WLAN wie per Kabel. Vorhandene Termux-Apps aus fremder Quelle werden erkannt und auf Nachfrage entfernt — mit deutlicher Warnung, dass dabei auch das Termux-Dateisystem verschwindet. GitHub statt F-Droid, weil es dort Termux:X11 in einer sharedUid-Variante gibt. Die läuft in Termux' Prozessgruppe und erbt dessen Akku-Ausnahmen; die normale Variante ist eine eigenständige Hintergrund-App, die Android drosselt. Bei ROMs wie ColorOS ist das der Unterschied zwischen 'läuft über Nacht' und 'war morgens weg'. Die Asset-Auswahl arbeitet mit einer Rangfolge statt eines festen Namens: stabile Veröffentlichungen vor Vorabversionen, und bei termux-app die Variante apt-android-7 vor dem Altbau apt-android-5, der sonst auf einem aktuellen Gerät gewählt würde. Korrektur zur bisherigen Dokumentation: Termux:X11 ist NICHT generell von der Signaturbindung ausgenommen. Nur die normale Variante ist es, die sharedUid- Fassung setzt GitHub-Termux voraus. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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:
|
||||
|
||||
Executable
+197
@@ -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/tty || WEG=n
|
||||
case "${WEG:-n}" in
|
||||
j|J)
|
||||
for p in "${VORHANDEN[@]}"; do
|
||||
if adb uninstall "$p" >/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
|
||||
+25
-9
@@ -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 </dev/tty || OEFFNEN=n
|
||||
case "${OEFFNEN:-j}" in
|
||||
if [ "$TROCKEN" != 1 ] && [ -x "$HIER/install-termux.sh" ]; then
|
||||
cat <<'TEXT'
|
||||
|
||||
Das muss aber niemand von Hand machen: install-termux.sh lädt alle vier
|
||||
Apps von GitHub und installiert sie über die bestehende adb-Verbindung —
|
||||
per WLAN genauso wie per Kabel.
|
||||
TEXT
|
||||
printf '\n Jetzt automatisch installieren? [J/n] > '
|
||||
read -r AUTOINSTALL </dev/tty || AUTOINSTALL=n
|
||||
case "${AUTOINSTALL:-j}" in
|
||||
j|J|"")
|
||||
adb shell am start -a android.intent.action.VIEW \
|
||||
-d 'https://f-droid.org/packages/com.termux/' >/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 _ </dev/tty
|
||||
else
|
||||
fehl "Automatische Installation fehlgeschlagen."
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
hinweis "Dann von Hand — danach dieses Skript erneut aufrufen."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
printf '\n'
|
||||
hinweis "Danach dieses Skript erneut aufrufen."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Hintergrundbetrieb, Android-Standardebene ────────────────────────────────
|
||||
|
||||
+34
-14
@@ -26,23 +26,43 @@ Scheitert er, ist das ein früher Warnschuss fürs Gesamtkonzept, kein Detail.
|
||||
|
||||
### Termux installieren
|
||||
|
||||
**Nicht aus dem Play Store** — die Fassung dort wird seit Jahren nicht mehr gepflegt und
|
||||
ist für dieses Projekt unbrauchbar. Alle Bestandteile müssen aus **derselben Quelle**
|
||||
stammen, sonst passen die Signaturen nicht zusammen und die Zusatz-Apps verweigern den Dienst.
|
||||
```bash
|
||||
./provision/install-termux.sh
|
||||
```
|
||||
|
||||
| App | F-Droid | GitHub |
|
||||
Lädt alle vier Apps von GitHub und installiert sie über die bestehende
|
||||
adb-Verbindung — per WLAN genauso wie per Kabel. `provision.sh` bietet das von
|
||||
selbst an, wenn Termux fehlt.
|
||||
|
||||
#### Warum das ein eigenes Skript verdient
|
||||
|
||||
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 — und F-Droid und GitHub signieren verschieden. Mischt man die Quellen, scheitert
|
||||
die Installation mit `INSTALL_FAILED_SHARED_USER_INCOMPATIBLE`. Das ist der mit Abstand
|
||||
häufigste Stolperstein beim Einrichten.
|
||||
|
||||
Das Skript wählt durchgängig **GitHub**, aus zwei Gründen:
|
||||
|
||||
- Termux:X11 gibt es dort in einer **sharedUid-Variante**. Die läuft in Termux'
|
||||
Prozessgruppe und erbt dessen Akku-Ausnahmen. Die normale Variante ist eine
|
||||
eigenständige Hintergrund-App, die Android drosselt — bei ROMs wie ColorOS der
|
||||
Unterschied zwischen „läuft über Nacht" und „war morgens weg".
|
||||
- Eine Quelle, ein Schlüssel, keine Mischmasch-Fehler.
|
||||
|
||||
**Nicht aus dem Play Store** — die Fassung dort wird seit Jahren nicht mehr gepflegt.
|
||||
|
||||
Von Hand geht es natürlich auch, dann aber konsequent alles aus **einer** Quelle:
|
||||
|
||||
| App | GitHub | F-Droid |
|
||||
|---|---|---|
|
||||
| Termux | [f-droid.org](https://f-droid.org/packages/com.termux/) | [Releases](https://github.com/termux/termux-app/releases/latest) |
|
||||
| Termux:API | [f-droid.org](https://f-droid.org/packages/com.termux.api/) | [Releases](https://github.com/termux/termux-api/releases/latest) |
|
||||
| Termux:Boot | [f-droid.org](https://f-droid.org/packages/com.termux.boot/) | [Releases](https://github.com/termux/termux-boot/releases/latest) |
|
||||
| Termux:X11 | — | [Releases](https://github.com/termux/termux-x11/releases) (Nightly, `app-universal-debug.apk`) |
|
||||
| Termux | [Releases](https://github.com/termux/termux-app/releases/latest) | [f-droid.org](https://f-droid.org/packages/com.termux/) |
|
||||
| Termux:API | [Releases](https://github.com/termux/termux-api/releases/latest) | [f-droid.org](https://f-droid.org/packages/com.termux.api/) |
|
||||
| Termux:Boot | [Releases](https://github.com/termux/termux-boot/releases/latest) | [f-droid.org](https://f-droid.org/packages/com.termux.boot/) |
|
||||
| Termux:X11 | [Releases](https://github.com/termux/termux-x11/releases) | — |
|
||||
|
||||
Termux:X11 gibt es nur bei GitHub. Wer die anderen drei von F-Droid nimmt, muss
|
||||
Termux:X11 trotzdem von dort holen — das ist in Ordnung, weil Termux:X11 eine
|
||||
eigenständige App ohne Signaturbindung an Termux ist.
|
||||
|
||||
Fehlt Termux, bietet `provision.sh` an, die Download-Seite direkt auf dem Telefon
|
||||
zu öffnen.
|
||||
Bei F-Droid-Termux muss für Termux:X11 die **normale** Variante genommen werden
|
||||
(`termux-x11-universal-debug.apk`), nicht die sharedUid-Fassung.
|
||||
|
||||
**Ein USB-Kabel wird nicht gebraucht.** Ab Android 11 geht die Ersteinrichtung über
|
||||
WLAN — `provision.sh` fragt beim Start, ob per Kabel oder per Netz verbunden werden
|
||||
|
||||
Reference in New Issue
Block a user