mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-10-09 02:54:14 +00:00
209 lines
5.6 KiB
Bash
Executable file
209 lines
5.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Recover an Android wireless-debugging connection when `adb connect` fails
|
|
# even though the device's TCP port is reachable. If Android has forgotten the
|
|
# host certificate, the script guides you through pairing again.
|
|
#
|
|
# Usage:
|
|
# scripts/fix_adb_connection.sh [PORT]
|
|
# scripts/fix_adb_connection.sh [HOST:PORT]
|
|
#
|
|
# The defaults below are the most recently used development device.
|
|
|
|
set -u
|
|
|
|
DEFAULT_HOST="10.99.0.213"
|
|
DEFAULT_PORT="34483"
|
|
MAX_ATTEMPTS=3
|
|
|
|
usage() {
|
|
sed -n '2,10p' "$0"
|
|
}
|
|
|
|
case "${1:-}" in
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
esac
|
|
|
|
HOST="$DEFAULT_HOST"
|
|
PORT="$DEFAULT_PORT"
|
|
|
|
if [ "$#" -gt 2 ]; then
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
if [ "$#" -eq 2 ]; then
|
|
HOST="$1"
|
|
PORT="$2"
|
|
elif [ "$#" -eq 1 ]; then
|
|
case "$1" in
|
|
*:*)
|
|
HOST="${1%:*}"
|
|
PORT="${1##*:}"
|
|
;;
|
|
*[!0-9]*) HOST="$1" ;;
|
|
*) PORT="$1" ;;
|
|
esac
|
|
fi
|
|
|
|
case "$PORT" in
|
|
''|*[!0-9]*)
|
|
echo "invalid port: $PORT" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
if [ "$PORT" -lt 1 ] || [ "$PORT" -gt 65535 ]; then
|
|
echo "port must be between 1 and 65535" >&2
|
|
exit 2
|
|
fi
|
|
|
|
command -v nc >/dev/null || {
|
|
echo "missing required tool: nc" >&2
|
|
exit 1
|
|
}
|
|
|
|
# Prefer the platform-tools installation used by Flutter/Android Studio. Using
|
|
# a Homebrew adb client against an Android SDK adb daemon (or vice versa) makes
|
|
# daemon ownership and diagnostics unnecessarily unpredictable.
|
|
if [ -n "${ANDROID_SDK_ROOT:-}" ] && [ -x "$ANDROID_SDK_ROOT/platform-tools/adb" ]; then
|
|
ADB="$ANDROID_SDK_ROOT/platform-tools/adb"
|
|
elif [ -n "${ANDROID_HOME:-}" ] && [ -x "$ANDROID_HOME/platform-tools/adb" ]; then
|
|
ADB="$ANDROID_HOME/platform-tools/adb"
|
|
elif [ -x "$HOME/Library/Android/sdk/platform-tools/adb" ]; then
|
|
ADB="$HOME/Library/Android/sdk/platform-tools/adb"
|
|
else
|
|
ADB="$(command -v adb || true)"
|
|
fi
|
|
|
|
if [ -z "$ADB" ]; then
|
|
echo "missing required tool: adb" >&2
|
|
exit 1
|
|
fi
|
|
|
|
ENDPOINT="$HOST:$PORT"
|
|
|
|
echo "Checking $ENDPOINT directly..."
|
|
if [ "$(uname -s)" = "Darwin" ]; then
|
|
NC_ARGS=(-G 3 -z)
|
|
else
|
|
NC_ARGS=(-w 3 -z)
|
|
fi
|
|
|
|
if ! nc "${NC_ARGS[@]}" "$HOST" "$PORT" >/dev/null 2>&1; then
|
|
echo "The TCP port is not reachable, so restarting ADB cannot fix it." >&2
|
|
echo "Check that Wireless debugging is enabled and that $PORT is the current connection port." >&2
|
|
exit 1
|
|
fi
|
|
echo "TCP port is reachable."
|
|
|
|
# Prevent Bonjour/mDNS from adding a second transport for the same device while
|
|
# this script establishes the explicit host:port connection.
|
|
export ADB_MDNS_AUTO_CONNECT=0
|
|
|
|
LAST_OUTPUT=""
|
|
PAIRING_REQUIRED=0
|
|
ADB_LOG="${TMPDIR:-/tmp}/adb.$(id -u).log"
|
|
attempt=1
|
|
while [ "$attempt" -le "$MAX_ATTEMPTS" ]; do
|
|
echo "ADB reconnect attempt $attempt/$MAX_ATTEMPTS..."
|
|
|
|
# `adb kill-server` sometimes leaves the macOS daemon alive. Killing only
|
|
# this user's exact `adb` processes clears that stale network-permission
|
|
# state without requiring sudo or affecting other users.
|
|
"$ADB" kill-server >/dev/null 2>&1 || true
|
|
pkill -x -u "$(id -u)" adb >/dev/null 2>&1 || true
|
|
|
|
"$ADB" start-server >/dev/null 2>&1
|
|
"$ADB" disconnect "$ENDPOINT" >/dev/null 2>&1 || true
|
|
|
|
LAST_OUTPUT="$("$ADB" connect "$ENDPOINT" 2>&1)"
|
|
echo "$LAST_OUTPUT"
|
|
|
|
if "$ADB" -s "$ENDPOINT" get-state 2>/dev/null | grep -qx device; then
|
|
echo
|
|
echo "Connected successfully: $ENDPOINT"
|
|
"$ADB" -s "$ENDPOINT" shell getprop ro.product.model 2>/dev/null \
|
|
| sed 's/^/Device: /'
|
|
exit 0
|
|
fi
|
|
|
|
if [ -f "$ADB_LOG" ] \
|
|
&& tail -80 "$ADB_LOG" | grep -qE 'CERTIFICATE_UNKNOWN|certificate unknown'; then
|
|
PAIRING_REQUIRED=1
|
|
break
|
|
fi
|
|
|
|
attempt=$((attempt + 1))
|
|
[ "$attempt" -le "$MAX_ATTEMPTS" ] && sleep 1
|
|
done
|
|
|
|
if [ "$PAIRING_REQUIRED" -eq 1 ]; then
|
|
echo
|
|
echo "Android rejected this computer's ADB certificate. Pairing is required."
|
|
echo "On the phone, open:"
|
|
echo " Settings > System > Developer options > Wireless debugging"
|
|
echo " Pair device with pairing code"
|
|
|
|
if [ ! -t 0 ]; then
|
|
echo "Run this script in an interactive terminal to enter the pairing port and code." >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf "Pairing port: "
|
|
IFS= read -r PAIRING_PORT
|
|
case "$PAIRING_PORT" in
|
|
''|*[!0-9]*)
|
|
echo "invalid pairing port: $PAIRING_PORT" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
if [ "$PAIRING_PORT" -lt 1 ] || [ "$PAIRING_PORT" -gt 65535 ]; then
|
|
echo "pairing port must be between 1 and 65535" >&2
|
|
exit 2
|
|
fi
|
|
|
|
printf "Pairing code: "
|
|
IFS= read -r PAIRING_CODE
|
|
case "$PAIRING_CODE" in
|
|
''|*[!0-9]*)
|
|
echo "invalid pairing code" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
PAIR_OUTPUT="$(printf '%s\n' "$PAIRING_CODE" | "$ADB" pair "$HOST:$PAIRING_PORT" 2>&1)"
|
|
PAIRING_CODE=""
|
|
echo "$PAIR_OUTPUT"
|
|
if ! printf '%s' "$PAIR_OUTPUT" | grep -q "Successfully paired"; then
|
|
echo "Pairing failed. Reopen the pairing dialog for a fresh port and code." >&2
|
|
exit 1
|
|
fi
|
|
|
|
LAST_OUTPUT="$("$ADB" connect "$ENDPOINT" 2>&1)"
|
|
echo "$LAST_OUTPUT"
|
|
if "$ADB" -s "$ENDPOINT" get-state 2>/dev/null | grep -qx device; then
|
|
echo
|
|
echo "Paired and connected successfully: $ENDPOINT"
|
|
"$ADB" -s "$ENDPOINT" shell getprop ro.product.model 2>/dev/null \
|
|
| sed 's/^/Device: /'
|
|
exit 0
|
|
fi
|
|
|
|
echo "Pairing succeeded, but the connection port failed. Check that $PORT is still current." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo >&2
|
|
echo "ADB could not connect after $MAX_ATTEMPTS clean restarts." >&2
|
|
if printf '%s' "$LAST_OUTPUT" | grep -q "No route to host"; then
|
|
echo "The port is reachable, but the ADB daemon is being denied local-network access." >&2
|
|
if [ "$(uname -s)" = "Darwin" ]; then
|
|
echo "Toggle your terminal app under System Settings > Privacy & Security > Local Network," >&2
|
|
echo "then run this script again." >&2
|
|
fi
|
|
fi
|
|
exit 1
|