在开发板上操作:
设置 → 系统 → 开发者选项 → 无线调试 → 开启开关
点击 「配对码配对设备」,会显示 IP 地址、端口和 6 位配对码。
# 配对(配对码和端口从开发板获取)
adb pair 192.168.1.100:端口 配对码
# 连接(配对成功后显示的连接端口)
adb connect 192.168.1.100:34323
# 查看已连接的设备
adb devices
# 断开连接
adb disconnect 192.168.1.100:34323
注意:配对码有效期约 2-5 分钟,过期需重新生成。
Q: 无法连接,端口 5555 被拒绝?
开发板可能没有默认监听 5555 端口。改用无线调试方式连接,或通过以下命令设置端口:
adb shell setprop service.adb.tcp.port 5556
adb shell stop adbd
adb shell start adbd
注意:setprop 设置的端口在重启后失效,需重新设置。
Q: adb pair 失败,提示 "Unable to start pairing client"?
检查 ADB 版本是否过旧,确保版本 >= 30.0.3:
adb version
scrcpy 是一款开源的安卓屏幕镜像工具,支持实时画面显示和鼠标键盘控制,延迟极低。
下载地址:https://github.com/Genymobile/scrcpy/releases
选择 scrcpy-win64-v4.0.zip,解压即可使用,无需安装。
# 连接已通过 ADB 连接的设备
scrcpy
# 指定设备(多设备时)
scrcpy -s 192.168.1.100:34323
# 窗口模式(默认)
scrcpy
# 全屏模式
scrcpy --fullscreen
# 限定分辨率(省带宽)
scrcpy --max-size 1024
# 关闭屏幕(仅显示画面,设备屏幕熄灭)
scrcpy --turn-screen-off
| 快捷键 | 功能 |
|---|---|
| 鼠标左键 | 点击 |
| 鼠标右键 | 返回 |
| 鼠标中键 | Home |
| Ctrl+H | Home |
| Ctrl+S | 截屏 |
| Ctrl+O | 关闭屏幕 |
| Ctrl+↑ | 音量加 |
| Ctrl+↓ | 音量减 |
这是一个 Web 界面工具,点按钮即可获取当前屏幕的所有可点击控件信息。
python inspect_ui.py
浏览器会自动打开 http://127.0.0.1:18889,点击 刷新 按钮即可获取当前界面的控件列表。
| 坐标 | 控件 | 文字 | ID |
|---|---|---|---|
| [175,788][295,875] | TextView | "深度清洁" | |
| [680,1024][760,1080] | ImageView | sys_power | |
| [45,852][165,939] | TextView | "启动" |
控件 bounds 格式为 [left,top][right,bottom],点击时取中心坐标:
x = (left + right) / 2
y = (top + bottom) / 2
示例:[175,788][295,875] → d.click(235, 831)
import uiautomator2 as u2
d = u2.connect()
# 截图
d.screenshot("screen.png")
# 获取当前界面所有控件(XML 格式)
xml = d.dump_hierarchy()
# 获取当前前台应用
info = d.app_current()
print(info)
pip install uiautomator2
python -m uiautomator2 init
init 命令会在开发板上安装 ATX 代理服务,后续所有操作都通过它执行。
import uiautomator2 as u2
import time
d = u2.connect()
# 获取设备信息
print(d.info)
# 启动应用
d.app_start("com.android.settings")
# 点击文字
d(text="设置").click()
# 点击坐标
d.click(235, 831)
# 输入文字
d.send_keys("hello")
# 滑动
d.swipe(500, 1000, 500, 200)
# 截图
d.screenshot("screen.png")
# 等待元素出现
d(text="确定").wait(timeout=5)
d(text="确定").click()
# 获取控件是否存在
if d(text="确定").exists:
d(text="确定").click()
import uiautomator2 as u2
import time
d = u2.connect()
# 等待界面加载
time.sleep(2)
# 点击"深度清洁"
d(text="深度清洁").click()
time.sleep(1)
# 点击"启动"
d(text="启动").click()
time.sleep(3)
# 截图验证
d.screenshot("result.png")
d(text="登录").click() # 按文字
d(resourceId="com.xx:id/btn_login").click() # 按 ID
d(className="android.widget.Button").click() # 按类型
| 工具 | 用途 | 运行方式 |
|---|---|---|
adb | 设备连接、文件传输、shell | 命令行 |
scrcpy | 实时画面、鼠标控制 | 单窗口 |
inspect_ui.py | 获取控件坐标/文字/ID | Web 页面 |
uiautomator2 | 自动化脚本 | Python 脚本 |
1. adb connect → 连接设备
2. scrcpy → 实时看屏幕操作
3. inspect_ui.py → 点击"刷新"获取控件信息
4. 写 Python 脚本 → 用 uiautomator2 自动化
setprop 设置的端口不会持久化d.dump_hierarchy() 每次耗时约 400ms,不需要追求太高的刷新频率python -m uiautomator2 init 安装 ATX 代理服务# Pair (code & port from device: Settings → Developer options → Wireless debugging → Pair with pairing code)
adb pair 192.168.1.100:PORT PAIRING_CODE
# Connect (use port shown after pairing)
adb connect 192.168.1.100:34323
# Verify
adb devices
# Disconnect
adb disconnect 192.168.1.100:34323
Pairing code expires in ~2-5 minutes. Regenerate by re-entering the pairing screen.
adb shell setprop service.adb.tcp.port 5556
adb shell stop adbd
adb shell start adbd
Note: setprop resets on reboot.
adb pair fails "Unable to start pairing client" → Check ADB version >= 30.0.3127.0.0.1 instead of localhost, or close FiddlerDownload from: https://github.com/Genymobile/scrcpy/releases
scrcpy # Auto-connect to ADB device
scrcpy -s 192.168.1.100:34323 # Specific device
scrcpy --turn-screen-off # Device screen off, PC only
scrcpy --max-size 1024 # Limit resolution
scrcpy --fullscreen # Fullscreen mode
| Input | Action |
|---|---|
| Left mouse | Tap |
| Right mouse | Back |
| Middle mouse | Home |
| Ctrl+H | Home |
| Ctrl+S | Screenshot |
| Ctrl+O | Turn off screen |
inspect_ui.py)A self-contained Python web server with a refresh button.
import uiautomator2 as u2
import xml.etree.ElementTree as ET
import json
from http.server import HTTPServer, BaseHTTPRequestHandler
import webbrowser
d = u2.connect()
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/":
self.send_response(200)
self.send_header("Content-Type", "text/html;charset=utf-8")
self.end_headers()
with open(__file__.replace('.py', '.html')) as f:
self.wfile.write(f.read().encode())
elif self.path == "/refresh":
xml = d.dump_hierarchy()
root = ET.fromstring(xml)
cur = d.app_current()
pkg = cur.get('package') or cur.get('currentPackageName', '')
items = []
for node in root.iter("node"):
if node.get("clickable") == "true":
text = node.get("text", "") or ""
rid = node.get("resource-id", "") or ""
bounds = node.get("bounds", "")
cls = node.get("class", "").split(".")[-1]
if text or rid:
items.append({"text": text, "id": rid.split("/")[-1], "bounds": bounds, "class": cls})
data = {"pkg": pkg, "items": items, "count": len(list(root.iter()))}
self.send_response(200)
self.send_header("Content-Type", "application/json;charset=utf-8")
self.end_headers()
self.wfile.write(json.dumps(data, ensure_ascii=False).encode())
httpd = HTTPServer(("127.0.0.1", 18889), Handler)
webbrowser.open("http://127.0.0.1:18889")
httpd.serve_forever()
Run: python inspect_ui.py → browser opens at http://127.0.0.1:18889 → click Refresh
Bounds format: [left,top][right,bottom]
x = (left + right) / 2
y = (top + bottom) / 2
Example: [175,788][295,875] → d.click(235, 831)
pip install uiautomator2
python -m uiautomator2 init # Installs ATX agent on device
d(text="登录").click() # By text
d(resourceId="com.xx:id/btn").click() # By resource ID
d(className="android.widget.Button").click() # By class
d.click(235, 831) # By coordinate
import uiautomator2 as u2
import time
d = u2.connect()
d.app_start("com.android.settings") # Launch app
d.send_keys("hello") # Input text
d.swipe(500, 1000, 500, 200) # Swipe
d(text="确认").wait(timeout=5) # Wait for element
d(text="确认").click() # Click after wait
d.screenshot("screen.png") # Screenshot
import uiautomator2 as u2
import time
d = u2.connect()
time.sleep(2)
d(text="深度清洁").click()
time.sleep(1)
d(text="启动").click()
time.sleep(3)
d.screenshot("result.png")
Terminal 1: adb connect 192.168.1.100:34323
Terminal 2: scrcpy -s 192.168.1.100:34323
Terminal 3: python inspect_ui.py → http://127.0.0.1:18889
Terminal 4: Write & run automation script
d.dump_hierarchy() takes ~400ms per call; don't set too fast refreshpython -m uiautomator2 init once before first use127.0.0.1Place in .opencode/skills/android-remote-debug/SKILL.md or add the path to skills.paths in opencode.json:
{
"skills": {
"paths": [".opencode/skills"]
}
}
Place anywhere and load as a reference file when working on Android automation.