| name | android-adb-connect |
| description | Connect to an Android phone over ADB wireless (Galaxy S25 at meain's setup), install/launch APKs, take screenshots, and drive the UI via uiautomator. Triggers: "connect to phone", "adb connect", "test on phone", "screenshot the phone", "install on phone", "phone is at 192.168.1.3", any task that needs to drive an Android device from the host.
|
| argument-hint | [host:port or pairing code] |
Connect to Android phone over ADB wireless
This skill captures the actual quirks of meain's setup. The phone is a Samsung Galaxy S25 on the same WiFi as the host. The ADB SDK lives at ~/Android/sdk-edo (not the system path) — always export ANDROID_HOME=$HOME/Android/sdk-edo before running adb.
When to use
- The user says "connect to the phone", "test on phone", "adb connect …"
- They paste a
host:port and optionally a 6-digit pairing code
- You need to install an APK on the device, drive the UI, or screenshot it
- A previous connection dropped (port rotates every time wireless debugging is toggled)
Step 1 — set up the environment
export ANDROID_HOME=$HOME/Android/sdk-edo
export PATH=$ANDROID_HOME/platform-tools:$PATH
adb devices
If adb isn't found, the SDK is at ~/Android/sdk-edo/platform-tools/adb.
If any entry shows status device, check if it's the Galaxy S25 before proceeding to connect:
adb -s <device-id> shell getprop ro.product.model
Use that ID with -s for all subsequent commands.
Step 2 — connect
Already paired (the common case)
The phone remembers the pairing across reboots, but the wireless port changes every time Wireless Debugging is toggled. The user will typically paste a new host:port — use it directly:
adb connect 192.168.1.3:38181
If that fails with failed to authenticate or hangs, the pairing has expired — go to Step 2b.
First-time or expired pairing
The user needs to open Settings → Developer options → Wireless debugging → Pair device with pairing code on the phone. That screen shows a host:pairing_port and a 6-digit code. They are separate from the regular host:port shown on the main Wireless debugging screen.
adb pair 192.168.1.3:40319
adb pair 192.168.1.3:40319 657538
Then connect using the regular (non-pairing) port shown on the main Wireless debugging screen:
adb connect 192.168.1.3:38181
Discovering the port
If the user can't read the port off the phone, try mDNS:
adb mdns services
It lists adb-tls-pairing and adb-tls-connect entries with their ports. The pairing entry rotates each time the pairing code screen is opened.
TLS failures
SSLV3_ALERT_CERTIFICATE_UNKNOWN or "TLS handshake failed" means the host and phone disagree on the pairing — re-pair from scratch via Step 2b. Don't retry the same adb connect in a loop.
Step 3 — verify and identify
adb devices
Always pass -s <host:port> to subsequent commands when more than one device is listed (the adb-RZGY... mDNS entry can show up alongside the IP one).
Step 4 — common operations
Install / launch an app
adb -s 192.168.1.3:38181 install -r app/build/outputs/apk/debug/app-debug.apk
adb -s 192.168.1.3:38181 shell am force-stop com.example.app
adb -s 192.168.1.3:38181 shell am start -n com.example.app/.MainActivity
Screenshot
adb -s 192.168.1.3:38181 exec-out screencap -p > /tmp/phone.png
Drive the UI (taps, text)
Coordinates are in the device's native resolution (1080×2340 on the S25). Don't scale to display size. Get exact bounds via:
adb -s 192.168.1.3:38181 shell uiautomator dump /sdcard/window.xml >/dev/null
adb -s 192.168.1.3:38181 shell cat /sdcard/window.xml \
| tr '>' '\n' \
| grep -oE '(text|content-desc|bounds)="[^"]+'
Then tap the center of bounds="[x1,y1][x2,y2]":
adb -s 192.168.1.3:38181 shell input tap 540 1200
adb -s 192.168.1.3:38181 shell input text "hello%sworld"
adb -s 192.168.1.3:38181 shell input keyevent KEYCODE_BACK
adb -s 192.168.1.3:38181 shell input keyevent KEYCODE_WAKEUP
Quirks of input text:
- Spaces must be
%s, not literal spaces.
- Avoid
! — zsh history expansion can trigger before the command reaches the device.
- Newlines aren't supported; use
KEYCODE_ENTER separately.
Keep screen awake during testing
adb -s 192.168.1.3:38181 shell svc power stayon true
adb -s 192.168.1.3:38181 shell svc power stayon false
Logs
adb -s 192.168.1.3:38181 logcat -d -t 300 | grep com.example.app
Pulling the app database (Room WAL gotcha)
adb pull of just the .db file is incomplete because Room uses WAL mode. Force-stop the app first to flush, then pull all three files:
adb -s 192.168.1.3:38181 shell am force-stop com.example.app
for f in app.db app.db-wal app.db-shm; do
adb -s 192.168.1.3:38181 shell "run-as com.example.app cat databases/$f 2>/dev/null" > /tmp/$f
done
sqlite3 /tmp/app.db "SELECT ..."
The device's sqlite3 binary is missing on stock Samsung — always pull and query locally.
Project context
For the Edo project at /Users/meain/dev/src/edo, see its CLAUDE.md for the install/launch/screenshot pattern with the actual package name (com.edo.app).