不止于测试:用uiautomator2打造你的Android手机自动化“外挂”
在数字生活高度渗透的今天,手机早已成为我们身体的延伸。每天重复的签到、抢购、消息回复等操作不仅消耗时间,更让人感到疲惫。有没有一种方式,能让手机像拥有"自主意识"一样,自动完成这些琐碎任务?这就是uiautomator2带给我们的可能性——它远不止是一个测试工具,更是解放双手的自动化利器。
1. 为什么选择uiautomator2?
提到Android自动化,很多人会想到Appium或ADB命令。但uiautomator2在易用性和功能深度上找到了完美平衡:
- 无界面依赖:不同于需要开启开发者选项中"指针位置"的辅助功能方案,它直接与系统服务交互
- Python生态:所有操作都可以用Python脚本控制,轻松集成到现有工作流
- 全面覆盖:从基础点击到复杂手势,从应用管理到设备控制,API设计极其完备
- 性能优势:相比基于WebDriver的方案,执行速度更快,资源占用更低
我曾用它在凌晨3点自动抢到限量球鞋,也实现了微信消息的智能回复原型。这些看似"黑科技"的操作,其实只需要几十行代码。
2. 环境搭建:5分钟快速入门
2.1 基础环境配置
确保你的开发环境已经具备:
# 检查Python版本(需要3.6+) python --version # 安装基础工具 pip install uiautomator2 weditor手机端需要开启USB调试模式:
- 进入设置 → 关于手机 → 连续点击"版本号"7次开启开发者模式
- 返回设置 → 系统 → 开发者选项 → 开启USB调试
- 连接电脑后,在手机上允许调试请求
提示:部分厂商手机需要额外开启"USB安装"和"USB调试(安全设置)"
2.2 设备连接方式对比
| 连接方式 | 命令示例 | 适用场景 | 稳定性 |
|---|---|---|---|
| USB直连 | d = u2.connect() | 开发调试 | ★★★★★ |
| WiFi连接 | d = u2.connect('192.168.1.100:7912') | 远程控制 | ★★★☆☆ |
| 多设备指定 | d = u2.connect('设备序列号') | 多机操作 | ★★★★☆ |
推荐初次使用选择USB连接,稳定性最佳。连接成功后可以打印设备信息验证:
import uiautomator2 as u2 d = u2.connect() print(d.info)3. 实战案例:从自动化到"外挂"
3.1 短视频自动刷播脚本
很多短视频平台会有观看时长奖励,手动操作既耗时又无聊。下面脚本实现自动滑动和随机间隔点赞:
import random import time def auto_swipe(d, count=100): width, height = d.window_size() for i in range(count): # 随机滑动距离和时长 start_y = height * 0.8 end_y = height * 0.2 duration = random.uniform(0.3, 0.8) # 滑动操作 d.swipe(width/2, start_y, width/2, end_y, duration) # 30%概率点赞 if random.random() > 0.7: d.click(width-100, height/2) # 随机间隔1-3秒 time.sleep(random.uniform(1, 3))优化技巧:
- 加入
random制造人类操作的不确定性 - 通过
window_size()适配不同分辨率设备 - 使用相对坐标而非绝对坐标值
3.2 微信自动回复原型
虽然完整实现消息自动回复需要更高权限,但我们可以监控特定联系人消息并模拟点击回复:
def wechat_auto_reply(d, contact_name, reply_content): # 启动微信 d.app_start('com.tencent.mm') # 等待主界面加载 d(text="微信").wait(timeout=10) # 进入聊天列表 d(resourceId="com.tencent.mm:id/cns").click() # 搜索指定联系人 d(resourceId="com.tencent.mm:id/iq").set_text(contact_name) time.sleep(1) # 监控新消息 watcher = d.watcher("NEW_MSG") watcher.when(resourceId="com.tencent.mm:id/aou").click() # 设置自动回复 def do_reply(): d(resourceId="com.tencent.mm:id/amr").set_text(reply_content) d(resourceId="com.tencent.mm:id/amv").click() watcher.when(text="发送").call(do_reply) watcher.start()注意:实际使用需考虑微信版本差异,建议先在测试环境验证
3.3 游戏日常任务自动化
以某热门手游为例,自动完成每日签到和简单任务:
def game_daily(d): # 启动游戏 d.app_start('com.game.example') # 等待加载完成 while not d(text="每日签到").exists: time.sleep(1) # 签到流程 if d(text="每日签到").exists: d(text="每日签到").click() time.sleep(1) d(text="领取").click() time.sleep(1) d.click(540, 1800) # 关闭弹窗 # 执行日常任务 task_positions = [ (200, 800), # 任务1坐标 (500, 800), # 任务2坐标 (800, 800) # 任务3坐标 ] for x, y in task_positions: d.click(x, y) time.sleep(3) d.press("back") # 返回键 time.sleep(1)定位技巧:
- 使用
weditor分析界面元素 - 对动态元素采用相对定位
- 关键操作后加入合理等待
4. 高级技巧与避坑指南
4.1 元素定位的六种武器
- 文本定位:
d(text="设置") - 资源ID定位:
d(resourceId="com.android.settings:id/title") - 组合定位:
d(className="android.widget.TextView", text="Wi-Fi") - 相对定位:
d(text="Wi-Fi").right(className="android.widget.Switch") - XPath定位:
d.xpath('//*[@content-desc="更多选项"]') - 图像识别:
d.image.click('button.png')
定位策略选择优先级:
资源ID > 文本 > 组合条件 > 相对定位 > XPath > 图像识别4.2 稳定性提升方案
等待策略对比表:
| 等待方式 | 代码示例 | 适用场景 | 超时处理 |
|---|---|---|---|
| 固定等待 | time.sleep(3) | 简单场景 | 不灵活 |
| 元素等待 | d(text="OK").wait(10) | 元素出现 | 抛出异常 |
| 全局超时 | d.implicitly_wait(15) | 通用设置 | 自动处理 |
| 智能等待 | while not condition: sleep(1) | 复杂条件 | 自定义逻辑 |
推荐实践:
# 设置合理的全局等待超时 d.implicitly_wait(10) # 关键操作添加显式等待 if d(text="同意").wait(timeout=5): d(text="同意").click() else: raise Exception("协议页面加载超时") # 复杂界面使用监控器 watcher = d.watcher("POPUP") watcher.when(text="确定").click() watcher.start()4.3 常见问题排查
问题1:点击无效
- 检查元素是否可点击
d(text="按钮").info['clickable'] - 尝试坐标点击
d.click(x, y) - 确认没有遮挡物
问题2:脚本在不同设备表现不一致
- 使用相对坐标而非绝对坐标
- 通过
window_size()适配分辨率 - 增加异常处理和重试机制
问题3:性能突然下降
- 关闭不必要的watcher
- 减少截图操作频率
- 重启uiautomator服务
d.service("uiautomator").restart()
5. 扩展应用:自动化生态构建
5.1 与Tasker联动
通过uiautomator2执行复杂操作,用Tasker设置触发条件:
- 将Python脚本打包为APK(使用Termux等工具)
- Tasker监测特定事件(如时间、通知等)
- 调用脚本执行自动化任务
5.2 搭建自动化服务器
将常用脚本部署为HTTP服务,实现远程触发:
from flask import Flask, request import uiautomator2 as u2 app = Flask(__name__) d = u2.connect() @app.route('/wechat/reply') def wechat_reply(): contact = request.args.get('contact') message = request.args.get('msg') # 调用之前的自动回复函数 wechat_auto_reply(d, contact, message) return "OK" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)5.3 数据采集与分析
结合Pandas进行行为数据收集和分析:
import pandas as pd from datetime import datetime data = [] def collect_action(action): data.append({ "time": datetime.now(), "action": action, "screen": d.app_current()['activity'] }) # 在操作中插入采集点 d.click(100, 200) collect_action("点击签到按钮") # 保存数据 df = pd.DataFrame(data) df.to_csv('action_log.csv', index=False)在实际项目中,我发现最耗时的不是编写脚本本身,而是处理各种边界情况和异常。比如某次自动签到失败,是因为系统弹出了新版协议确认框。后来我加入了弹窗监控机制,脚本稳定性大幅提升。