Python+ADB自动化控制安卓设备:从基础连接到实战应用
1. ADB与Python自动化控制入门刚接触安卓设备自动化时我被ADBAndroid Debug Bridge这个工具惊艳到了。它就像一把瑞士军刀能通过命令行完成各种设备操作。而Python作为胶水语言可以轻松封装ADB命令实现更复杂的自动化流程。要开始使用ADB首先需要在电脑上安装它。Windows用户可以直接下载platform-tools压缩包解压后记得把路径添加到系统环境变量。Mac用户更简单用Homebrew一行命令就能搞定brew install android-platform-tools。安装完成后在终端输入adb version就能验证是否成功。连接设备时有个小技巧先用USB线连接手机或平板开启开发者选项里的USB调试。第一次连接时设备上会弹出授权提示记得点击允许。这时运行adb devices如果看到设备序列号就说明连接成功了。我遇到过设备不识别的情况后来发现是USB线质量问题换根线就解决了。无线连接更方便先用USB执行adb tcpip 5555然后拔掉线运行adb connect 设备IP:5555就能无线控制了。不过要注意有些厂商会限制无线ADB比如华为EMUI需要额外开启仅充电模式下允许ADB调试。2. Python封装ADB基础操作用Python操作ADB的核心就是os.system()或subprocess模块。我更喜欢用subprocess因为它能更好地处理命令输出。比如获取设备分辨率import subprocess def get_device_resolution(): output subprocess.check_output([adb, shell, wm, size]) return output.decode().strip().split( )[2]封装点击操作时我发现直接使用input tap命令有时不够稳定。后来改用sendevent方式可靠性提升不少def precise_click(x, y): subprocess.run([adb, shell, input, tap, str(x), str(y)])滑动操作也很常用比如模拟上下滚动def swipe(start_x, start_y, end_x, end_y, duration300): cmd fadb shell input swipe {start_x} {start_y} {end_x} {end_y} {duration} subprocess.run(cmd, shellTrue)实际项目中我会把这些基础操作封装成类加入异常处理和重试机制。比如连接断开时自动重连操作失败时记录日志等。这样代码的健壮性会好很多。3. 游戏自动化实战案例用PythonADB实现游戏自动化最关键是解决两个问题如何获取游戏界面元素位置以及如何实现精准操作。获取坐标有几种方法开启开发者选项中的显示指针位置使用adb shell getevent -l监听触摸事件通过Scrcpy实时查看点击位置我做过一个简单的游戏辅助用PyAutoGUI监听键盘然后映射到屏幕点击import pyautogui import subprocess # 技能按键映射 skill_map { q: 500 1200, w: 700 1200, e: 900 1200, r: 1100 1200 } while True: key pyautogui.KEYBOARD_KEYS if key in skill_map: subprocess.run(fadb shell input tap {skill_map[key]}, shellTrue)更复杂的场景可以用图像识别定位。比如用OpenCV模板匹配找特定按钮import cv2 import numpy as np def find_button(button_img, threshold0.8): subprocess.run(adb exec-out screencap -p screen.png, shellTrue) screen cv2.imread(screen.png, 0) template cv2.imread(button_img, 0) res cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) loc np.where(res threshold) return list(zip(*loc[::-1]))[0] if len(loc[0]) 0 else None4. 使用Scrcpy增强控制体验Scrcpy真是个神器它能把安卓屏幕镜像到电脑还支持键鼠控制。安装很简单Mac:brew install scrcpyWindows:choco install scrcpy我最喜欢它的按键映射功能创建配置文件~/.config/scrcpy/scrcpy-keyboard.json{ mappings: [ { key: A, action: touch, x: 100, y: 500 }, { key: D, action: touch, x: 300, y: 500 } ] }然后运行scrcpy --keyboard scrcpy-keyboard.json就能用键盘控制了。相比纯ADB方案Scrcpy的延迟更低约30ms而且能看到实时画面。对于需要精准操作的游戏我会开启Scrcpy的高性能模式scrcpy --max-fps 60 --bit-rate 8M --max-size 1920这能显著提升画面流畅度。如果网络条件好还可以尝试无线连接adb tcpip 5555 scrcpy --tcpip设备IP5. 常见问题与性能优化在长期使用中我总结了一些常见坑点和优化技巧设备断连问题无线连接时可以写个守护进程定期检查连接状态。我常用的检查命令是adb get-state返回device表示正常。操作延迟优化批量执行命令时使用adb shell一次执行多个操作比单独执行快很多。比如commands [ input tap 100 200, sleep 0.1, input tap 300 400 ] subprocess.run([adb, shell, ;.join(commands)])分辨率适配不同设备分辨率不同最好用相对坐标。我通常会先获取设备分辨率然后计算比例width, height map(int, get_device_resolution().split(x)) def relative_click(rel_x, rel_y): abs_x int(width * rel_x) abs_y int(height * rel_y) precise_click(abs_x, abs_y)防检测技巧有些游戏会检测自动化操作。可以加入随机延迟和位置偏移import random import time def safe_click(x, y): offset_x random.randint(-5, 5) offset_y random.randint(-5, 5) delay random.uniform(0.1, 0.3) time.sleep(delay) precise_click(x offset_x, y offset_y)多设备管理当需要控制多个设备时要在命令中指定序列号device_serial 123abc subprocess.run(fadb -s {device_serial} shell input tap 100 200, shellTrue)6. 进阶应用场景除了游戏控制这套技术还能用在很多地方自动化测试结合pytest可以做UI自动化。我设计过一个自动遍历测试方案def test_app_screens(): screens [home, settings, profile] for screen in screens: navigate_to(screen) assert verify_screen(screen) take_screenshot(f{screen}.png)批量设备管理在公司有20台测试机需要同时操作时我用multiprocessing实现了并行控制from multiprocessing import Pool def run_on_device(serial): subprocess.run(fadb -s {serial} install app.apk, shellTrue) with Pool(4) as p: p.map(run_on_device, device_serials)数据采集定期截图并分析内容。我做过一个竞品监控工具import schedule import time def monitor_competitor(): subprocess.run(adb exec-out screencap -p screenshot.png, shellTrue) analyze_image(screenshot.png) schedule.every(6).hours.do(monitor_competitor) while True: schedule.run_pending() time.sleep(60)家庭自动化把旧手机改造成智能家居控制器。我用Flask做了个简单的web接口from flask import Flask app Flask(__name__) app.route(/click/x/y) def click(x, y): subprocess.run(fadb shell input tap {x} {y}, shellTrue) return OK在实际项目中我发现稳定性最关键。所以现在我的代码都会包含完善的日志和异常处理。比如连接断开自动重试操作失败记录上下文等。这些经验都是踩过坑才积累起来的。