@@ -0,0 +1,106 @@
1+#!/usr/bin/env bash
2+#
3+# Build the debug APK, then install and launch the app on a physically
4+# connected device (USB or wireless). Unlike scripts/run.sh, this never boots
5+# an emulator — it targets real hardware only.
6+#
7+# Usage:
8+# scripts/run-device.sh # build + install + launch on the connected device
9+# scripts/run-device.sh -s <serial> # target a specific device (see `adb devices`)
10+# scripts/run-device.sh -c 192.168.1.5 # adb connect over Wi-Fi first (host or host:port)
11+# scripts/run-device.sh --no-build # skip the Gradle build, just install + launch
12+# scripts/run-device.sh --release # build/install the release variant
13+#
14+set -euo pipefail
15+
16+APP_ID="soy.iko.opencode"
17+ACTIVITY=".MainActivity"
18+VARIANT="debug"
19+DO_BUILD=1
20+SERIAL=""
21+CONNECT=""
22+
23+while [[ $# -gt 0 ]]; do
24+ case "$1" in
25+ -s|--serial) SERIAL="$2"; shift 2 ;;
26+ -c|--connect) CONNECT="$2"; shift 2 ;;
27+ --no-build) DO_BUILD=0; shift ;;
28+ --release) VARIANT="release"; shift ;;
29+ -h|--help)
30+ awk 'NR>1 && /^#/ {sub(/^# ?/,""); print; next} NR>1 {exit}' "$0"
31+ exit 0 ;;
32+ *) echo "Unknown argument: $1" >&2; exit 2 ;;
33+ esac
34+done
35+
36+cd "$(dirname "$0")/.."
37+
38+# --- locate adb -------------------------------------------------------------
39+SDK="${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}"
40+find_tool() {
41+ local name="$1"
42+ if command -v "$name" >/dev/null 2>&1; then command -v "$name"; return; fi
43+ for d in "$SDK/platform-tools" "$SDK/cmdline-tools/latest/bin"; do
44+ [[ -x "$d/$name" ]] && { echo "$d/$name"; return; }
45+ done
46+ echo ""
47+}
48+ADB="$(find_tool adb)"
49+[[ -z "$ADB" ]] && { echo "error: 'adb' not found; set ANDROID_HOME / ANDROID_SDK_ROOT" >&2; exit 1; }
50+
51+# --- optional wireless connect ---------------------------------------------
52+if [[ -n "$CONNECT" ]]; then
53+ [[ "$CONNECT" == *:* ]] || CONNECT="$CONNECT:5555"
54+ echo ">> Connecting to $CONNECT..."
55+ "$ADB" connect "$CONNECT"
56+ SERIAL="${SERIAL:-$CONNECT}"
57+fi
58+
59+# --- pick a physical device (exclude emulators) -----------------------------
60+# Lists serials of connected, ready devices whose serial is NOT emulator-*.
61+physical_devices() {
62+ "$ADB" devices | awk 'NR>1 && $2=="device" && $1 !~ /^emulator-/ {print $1}'
63+}
64+
65+if [[ -z "$SERIAL" ]]; then
66+ DEVICES=()
67+ while IFS= read -r line; do [[ -n "$line" ]] && DEVICES+=("$line"); done < <(physical_devices)
68+ case "${#DEVICES[@]}" in
69+ 0) echo "error: no physical device connected (enable USB debugging, or use -c for Wi-Fi)" >&2; exit 1 ;;
70+ 1) SERIAL="${DEVICES[0]}" ;;
71+ *) echo "error: multiple devices connected; choose one with -s <serial>:" >&2
72+ printf ' %s\n' "${DEVICES[@]}" >&2
73+ exit 1 ;;
74+ esac
75+fi
76+echo ">> Target device: $SERIAL"
77+
78+# Confirm the chosen device is actually ready.
79+if ! "$ADB" -s "$SERIAL" get-state 2>/dev/null | grep -q '^device$'; then
80+ echo "error: device '$SERIAL' is not ready (unauthorized or offline?)" >&2
81+ exit 1
82+fi
83+
84+# --- build ------------------------------------------------------------------
85+if [[ "$VARIANT" == "release" ]]; then
86+ GRADLE_TASK="assembleRelease"
87+ APK="app/build/outputs/apk/release/app-release.apk"
88+else
89+ GRADLE_TASK="assembleDebug"
90+ APK="app/build/outputs/apk/debug/app-debug.apk"
91+fi
92+
93+if [[ "$DO_BUILD" -eq 1 ]]; then
94+ echo ">> Building ($GRADLE_TASK)..."
95+ ./gradlew "$GRADLE_TASK"
96+fi
97+[[ -f "$APK" ]] || { echo "error: APK not found at $APK (did the build run?)" >&2; exit 1; }
98+
99+# --- install + launch -------------------------------------------------------
100+echo ">> Installing $APK on $SERIAL..."
101+"$ADB" -s "$SERIAL" install -r "$APK"
102+
103+echo ">> Launching $APP_ID/$ACTIVITY..."
104+"$ADB" -s "$SERIAL" shell am start -n "$APP_ID/$ACTIVITY"
105+
106+echo ">> Done."