#!/usr/bin/env bash # Gemeinsame Hilfsfunktionen für die Provisioning-Skripte. # Wird eingebunden, nicht direkt ausgeführt. if [ -t 1 ]; then C_OK=$'\033[32m'; C_WARN=$'\033[33m'; C_ERR=$'\033[31m' C_HEAD=$'\033[1;36m'; C_DIM=$'\033[2m'; C_OFF=$'\033[0m' else C_OK=""; C_WARN=""; C_ERR=""; C_HEAD=""; C_DIM=""; C_OFF="" fi kopf() { printf '\n%s══ %s ══%s\n' "$C_HEAD" "$*" "$C_OFF"; } ok() { printf '%s ✓%s %s\n' "$C_OK" "$C_OFF" "$*"; } warn() { printf '%s !%s %s\n' "$C_WARN" "$C_OFF" "$*"; } fehl() { printf '%s ✗%s %s\n' "$C_ERR" "$C_OFF" "$*"; } hinweis() { printf '%s %s%s\n' "$C_DIM" "$*" "$C_OFF"; } # ── Das richtige adb finden ────────────────────────────────────────────────── # Debians Paket android-tools-adb liefert Version 29. 'adb pair' — und damit die # Kopplung über WLAN — kam erst mit platform-tools 30. Wer beides installiert hat, # bekommt je nach PATH-Reihenfolge mal das eine und mal das andere. Deshalb wird # hier gezielt eine Fassung gesucht, die 'pair' beherrscht, statt sich auf PATH # zu verlassen. # # Setzt ADB_BIN und definiert eine Shell-Funktion 'adb', die darauf zeigt — # so müssen die Aufrufstellen nichts wissen. # Bewusst ohne Pipe: 'adb pair' ohne Argumente beendet sich mit Code 1, weil es ein # Aufruffehler ist. Unter 'set -o pipefail' würde das die ganze Pipeline als # fehlgeschlagen gelten lassen — obwohl grep den Hilfetext gefunden hat. adb_kann_pair() { local aus aus="$("$1" pair 2>&1 || true)" case "$aus" in *"usage: adb pair"*) return 0 ;; esac return 1 } adb_version() { "$1" version 2>/dev/null | sed -n '2p' | sed 's/^Version //'; } adb_finden() { local kandidaten=() k # Eine ausdrücklich gesetzte Vorgabe gilt absolut — auch wenn sie kein 'pair' # kann. Wer ADB= setzt, meint es so; stillschweigend etwas anderes zu nehmen # wäre die unangenehmere Überraschung. if [ -n "${ADB:-}" ]; then if [ ! -x "$ADB" ]; then fehl "ADB=$ADB ist nicht ausführbar." return 1 fi ADB_BIN="$ADB" adb_kann_pair "$ADB_BIN" && return 0 || return 2 fi kandidaten+=( "$HOME/Android/Sdk/platform-tools/adb" "$HOME/Library/Android/sdk/platform-tools/adb" "${ANDROID_HOME:-/nonexistent}/platform-tools/adb" "${ANDROID_SDK_ROOT:-/nonexistent}/platform-tools/adb" ) # Alles, was in PATH steht, ebenfalls prüfen — in PATH-Reihenfolge. while IFS= read -r k; do kandidaten+=("$k"); done < <(type -pa adb 2>/dev/null) local erstes_gefundenes="" for k in "${kandidaten[@]}"; do [ -x "$k" ] || continue [ -n "$erstes_gefundenes" ] || erstes_gefundenes="$k" if adb_kann_pair "$k"; then ADB_BIN="$k" return 0 fi done # Keines kann pair. Das ältere trotzdem melden — für USB reicht es. if [ -n "$erstes_gefundenes" ]; then ADB_BIN="$erstes_gefundenes" return 2 fi return 1 } # Muss von jedem Skript einmal aufgerufen werden, bevor adb benutzt wird. adb_einrichten() { local rc adb_finden; rc=$? case $rc in 0) : ;; 2) warn "Gefundenes adb ist zu alt für die WLAN-Kopplung: $(adb_version "$ADB_BIN")" hinweis "$ADB_BIN" hinweis "'adb pair' gibt es erst ab platform-tools 30. Debians Paket" hinweis "android-tools-adb hängt auf Version 29 — damit geht nur USB." hinweis "Aktuelle Fassung: developer.android.com/tools/releases/platform-tools" ;; *) fehl "Kein adb gefunden." hinweis "Entweder android-tools-adb installieren (nur USB) oder die" hinweis "platform-tools von Google entpacken (USB und WLAN)." exit 1 ;; esac # Ab hier zeigt 'adb' immer auf die ausgewählte Fassung, unabhängig von PATH. # # Ist ein Gerät ausgewählt (ADB_SERIAL), wird -s ergänzt — aber nur bei # Unterbefehlen, die sich an ein bestimmtes Gerät richten. 'adb -s X connect' # oder 'adb -s X devices' wären Unsinn und würden fehlschlagen. adb() { case "${1:-}" in shell|push|pull|install|install-multiple|uninstall|forward|reverse| \ logcat|sync|reboot|remount|root|unroot|bugreport|wait-for-device) if [ -n "${ADB_SERIAL:-}" ]; then "$ADB_BIN" -s "$ADB_SERIAL" "$@" return fi ;; esac "$ADB_BIN" "$@" } return $rc } # ── Geräteauswahl ──────────────────────────────────────────────────────────── # Mehrere Geräte gleichzeitig sind der Normalfall, sobald man ein zweites Telefon # koppelt oder nebenher noch eines am Kabel hängt. Statt abzubrechen wird gefragt. ADB_SERIAL="${ADB_SERIAL:-}" adb_geraete() { adb devices | awk '$2 == "device" { print $1 }'; } geraet_beschreiben() { local serial="$1" hersteller modell hersteller=$("$ADB_BIN" -s "$serial" shell getprop ro.product.manufacturer 2>/dev/null | tr -d '\r') modell=$("$ADB_BIN" -s "$serial" shell getprop ro.product.model 2>/dev/null | tr -d '\r') printf '%s %s' "${hersteller:-?}" "${modell:-?}" } # Wählt ein Gerät aus und setzt ADB_SERIAL. # 0 = ein Gerät ausgewählt # 1 = gar kein Gerät verbunden geraet_waehlen() { local liste=() zeile i wahl while IFS= read -r zeile; do [ -n "$zeile" ] && liste+=("$zeile") done < <(adb_geraete) case ${#liste[@]} in 0) ADB_SERIAL=""; return 1 ;; 1) ADB_SERIAL="${liste[0]}"; return 0 ;; esac kopf "Mehrere Geräte verbunden" for i in "${!liste[@]}"; do printf ' [%d] %-24s %s\n' "$((i + 1))" "${liste[i]}" "$(geraet_beschreiben "${liste[i]}")" done printf '\n Welches Gerät soll eingerichtet werden? [1] > ' read -r wahl /dev/null && [ "$wahl" -le ${#liste[@]} ]; then ADB_SERIAL="${liste[$((wahl - 1))]}" ok "Gewählt: $ADB_SERIAL ($(geraet_beschreiben "$ADB_SERIAL"))" return 0 fi warn "Ungültige Auswahl — nehme das erste Gerät." ADB_SERIAL="${liste[0]}" return 0 }