#!/data/data/com.termux/files/usr/bin/bash set -euo pipefail HOST="127.0.0.1" CONNECT_PORT="" TIMEOUT_SECS=180 STATE_DIR="${TMPDIR:-/data/data/com.termux/files/usr/tmp}/adbw_pair" NOTIF_ID=9400 CLEANUP_OFFLINE=1 DEBUG=0 mkdir -p "$STATE_DIR" need() { command -v "$1" >/dev/null 2>&1; } die(){ echo "[!] $*" >&2; exit 1; } dbg(){ [[ "$DEBUG" == "1" ]] && echo "[DBG] $*" >&2 || true; } install_if_missing() { local pkgs=() need adb || pkgs+=("android-tools") need termux-notification || pkgs+=("termux-api") if ((${#pkgs[@]})); then echo "[*] Installing: ${pkgs[*]}" apt-get install -y "${pkgs[@]}" >/dev/null fi need adb || die "Missing adb. Install: pkg install android-tools" need termux-notification || die "Missing termux-notification. Install: pkg install termux-api (and install Termux:API app)" } cleanup_notif() { termux-notification-remove "$NOTIF_ID" >/dev/null 2>&1 || true } notify_ask_one() { # args: key title content local key="$1" title="$2" content="$3" local out="$STATE_DIR/$key.txt" rm -f "$out" # Force a "fresh" notification so Android plays sound each time termux-notification-remove "$NOTIF_ID" >/dev/null 2>&1 || true termux-notification \ --id "$NOTIF_ID" \ --ongoing \ --alert-once \ --priority max \ --title "$title" \ --content "$content" \ --sound \ --button1 "Answer" \ --button1-action "sh -lc 'echo \"\$REPLY\" > \"$out\"'" local start now start="$(date +%s)" while true; do if [[ -s "$out" ]]; then tr -d '\r\n' < "$out" return 0 fi now="$(date +%s)" if (( now - start >= TIMEOUT_SECS )); then return 1 fi sleep 1 done } ask_port_5digits() { # args: key title local key="$1" title="$2" local v="" while true; do v="$(notify_ask_one "$key" "$title" "(5 digits)")" || return 1 v="${v//[[:space:]]/}" [[ "$v" =~ ^[0-9]{5}$ ]] || continue echo "$v" return 0 done } ask_code_6digits() { local v="" while true; do v="$(notify_ask_one code "PAIR CODE" "(6 digits)")" || return 1 v="${v//[[:space:]]/}" [[ -n "$v" ]] || continue [[ "$v" =~ ^[0-9]+$ ]] || continue # Allow missing leading zeros, then normalize to exactly 6 digits if ((${#v} < 6)); then v="$(printf "%06d" "$v")" fi [[ "$v" =~ ^[0-9]{6}$ ]] || continue echo "$v" return 0 done } cleanup_offline_loopback() { local keep_serial="$1" # e.g. 127.0.0.1:42371 local line serial state while read -r line; do serial="$(echo "$line" | awk '{print $1}')" state="$(echo "$line" | awk '{print $2}')" [[ "$serial" == ${HOST}:* ]] || continue [[ "$state" == "offline" ]] || continue [[ "$serial" == "$keep_serial" ]] && continue adb disconnect "$serial" >/dev/null 2>&1 || true done < <(adb devices 2>/dev/null | tail -n +2 | sed '/^\s*$/d') } usage() { cat </dev/null 2>&1 || true echo "[*] adb: $(adb version | head -n 1)" if [[ -n "$CONNECT_PORT" ]]; then CONNECT_PORT="${CONNECT_PORT//[[:space:]]/}" [[ "$CONNECT_PORT" =~ ^[0-9]{5}$ ]] || die "Invalid --connect-port (must be 5 digits): '$CONNECT_PORT'" else echo "[*] Asking CONNECT PORT..." CONNECT_PORT="$(ask_port_5digits connect "CONNECT PORT")" || die "Timeout waiting CONNECT PORT." fi echo "[*] Asking PAIR PORT..." local pair_port pair_port="$(ask_port_5digits pair "PAIR PORT")" || die "Timeout waiting PAIR PORT." echo "[*] Asking PAIR CODE..." local code code="$(ask_code_6digits)" || die "Timeout waiting PAIR CODE." local serial="${HOST}:${CONNECT_PORT}" adb disconnect "$serial" >/dev/null 2>&1 || true echo "[*] adb pair ${HOST}:${pair_port}" printf '%s\n' "$code" | adb pair "${HOST}:${pair_port}" echo "[*] adb connect $serial" adb connect "$serial" >/dev/null if [[ "$CLEANUP_OFFLINE" == "1" ]]; then cleanup_offline_loopback "$serial" fi echo "[*] Devices:" adb devices -l echo "[*] ADB check (shell):" adb -s "$serial" shell sh -lc 'echo "it worked: adb shell is working"; getprop ro.product.model; getprop ro.build.version.release' || true echo "[+] OK" } main "$@"