uiautomator2的完整能力
2025-10-24
深度学习
00

目录

🚀 uiautomator2完整能力清单
1. 📸 截图能力
2. 🔍 元素查找能力
3. 🎯 元素操作能力
4. 👆 手势操作能力
5. 📱 应用控制能力
6. 🔧 设备控制能力
7. ⏰ 等待和检测能力
8. 🚀 高级功能
9. 🤖 自动化能力

🚀 uiautomator2完整能力清单

1. 📸 截图能力

  • 全屏截图
  • 区域截图
  • 实时截图

2. 🔍 元素查找能力

  • 按文字查找:d.xpath('//*[@text="设置"]')
  • 按ID查找:d(resourceId="com.example:id/button")
  • 按类名查找:d(className="android.widget.Button")
  • 按内容描述查找:d(description="搜索")
  • 组合条件查找:d.xpath('//android.widget.Button[@text="确定"]')

3. 🎯 元素操作能力

  • 点击:element.click()
  • 长按:element.long_click()
  • 双击:element.double_click()
  • 输入文字:element.set_text("Hello")
  • 清除文字:element.clear_text()

4. 👆 手势操作能力

  • 滑动:d.swipe(x1, y1, x2, y2)
  • 拖拽:d.drag(x1, y1, x2, y2)
  • 缩放:d.pinch()
  • 旋转:d.rotate()

5. 📱 应用控制能力

  • 启动应用:d.app_start("com.example.app")
  • 停止应用:d.app_stop("com.example.app")
  • 获取当前应用:d.app_current()
  • 列出所有应用:d.app_list()

6. 🔧 设备控制能力

  • 按键操作:d.press('back'), d.press('home')
  • 音量控制:d.press('volume_up')
  • 屏幕控制:d.screen_on(), d.screen_off()

7. ⏰ 等待和检测能力

  • 等待元素:element.wait(timeout=10)
  • 检测存在:element.exists
  • 等待消失:element.wait_gone()

8. 🚀 高级功能

  • 坐标操作:d.click(x, y)
  • 元素属性:element.info
  • 屏幕信息:d.window_size()
  • 设备信息:d.info

9. 🤖 自动化能力

  • 完整的UI自动化测试
  • 批量操作
  • 条件判断
  • 循环执行

示例代码:

bash
展开代码
#!/usr/bin/env python3 """ uiautomator2 完整能力演示 展示uiautomator2的所有主要功能 """ import uiautomator2 as u2 import json import os import time from datetime import datetime from PIL import Image def demo_all_capabilities(): """ 演示uiautomator2的所有能力 """ print("🚀 uiautomator2 完整能力演示") print("="*60) try: # 连接设备 d = u2.connect() print(f"📱 已连接设备: {d.info.get('productName', 'Unknown')}") print(f"📱 设备信息: {d.info}") print() # 1. 截图能力 print("📸 1. 截图功能") print("-" * 30) timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") screenshot_path = f"demo_screenshot_{timestamp}.png" d.screenshot(screenshot_path) print(f"✅ 截图已保存: {screenshot_path}") print() # 2. 元素查找能力 print("🔍 2. 元素查找功能") print("-" * 30) # 2.1 按文字查找 print("按文字查找:") text_elements = d.xpath('//*[@text]').all() print(f" 找到 {len(text_elements)} 个有文字的元素") # 2.2 按类型查找 print("按类型查找:") buttons = d.xpath('//android.widget.Button').all() textviews = d.xpath('//android.widget.TextView').all() imageviews = d.xpath('//android.widget.ImageView').all() print(f" Button: {len(buttons)} 个") print(f" TextView: {len(textviews)} 个") print(f" ImageView: {len(imageviews)} 个") # 2.3 按ID查找 print("按ID查找:") id_elements = d.xpath('//*[@resource-id]').all() print(f" 找到 {len(id_elements)} 个有ID的元素") # 2.4 按内容描述查找 print("按内容描述查找:") desc_elements = d.xpath('//*[@content-desc]').all() print(f" 找到 {len(desc_elements)} 个有内容描述的元素") print() # 3. 元素操作能力 print("🎯 3. 元素操作功能") print("-" * 30) # 3.1 点击操作 print("点击操作:") clickable_elements = d.xpath('//*[@clickable="true"]').all() print(f" 找到 {len(clickable_elements)} 个可点击元素") # 3.2 输入操作 print("输入操作:") editable_elements = d.xpath('//*[@class="android.widget.EditText"]').all() print(f" 找到 {len(editable_elements)} 个可编辑元素") # 3.3 滑动操作 print("滑动操作:") print(" 支持上下左右滑动") print(" 支持指定距离和时间的滑动") print() # 4. 等待和检测能力 print("⏰ 4. 等待和检测功能") print("-" * 30) # 4.1 等待元素出现 print("等待元素出现:") try: # 等待某个元素出现(这里用系统时间作为示例) clock_element = d.xpath('//*[@resource-id="com.android.systemui:id/clock"]') if clock_element.exists: print(" ✅ 系统时钟元素存在") else: print(" ❌ 系统时钟元素不存在") except: print(" ⚠️ 无法检测系统时钟") # 4.2 检测应用状态 print("检测应用状态:") current_app = d.app_current() print(f" 当前应用: {current_app.get('package', 'Unknown')}") print(f" 应用名称: {current_app.get('name', 'Unknown')}") print() # 5. 手势操作能力 print("👆 5. 手势操作功能") print("-" * 30) print("支持的手势:") print(" - 点击 (click)") print(" - 长按 (long_click)") print(" - 双击 (double_click)") print(" - 滑动 (swipe)") print(" - 拖拽 (drag)") print(" - 缩放 (pinch)") print(" - 旋转 (rotate)") print() # 6. 应用控制能力 print("📱 6. 应用控制功能") print("-" * 30) # 6.1 应用启动 print("应用启动:") print(" - 启动应用: d.app_start(package_name)") print(" - 停止应用: d.app_stop(package_name)") print(" - 清除应用数据: d.app_clear(package_name)") # 6.2 应用信息 print("应用信息:") installed_apps = d.app_list() print(f" 已安装应用数量: {len(installed_apps)}") print(" 前5个应用:") for i, app in enumerate(installed_apps[:5], 1): print(f" {i}. {app}") print() # 7. 设备控制能力 print("🔧 7. 设备控制功能") print("-" * 30) # 7.1 设备信息 print("设备信息:") device_info = d.info print(f" 屏幕尺寸: {device_info.get('displayWidth')}x{device_info.get('displayHeight')}") print(f" 设备型号: {device_info.get('productName', 'Unknown')}") print(f" Android版本: {device_info.get('version', 'Unknown')}") # 7.2 设备操作 print("设备操作:") print(" - 返回键: d.press('back')") print(" - 主页键: d.press('home')") print(" - 菜单键: d.press('menu')") print(" - 电源键: d.press('power')") print(" - 音量键: d.press('volume_up/volume_down')") print() # 8. 高级功能 print("🚀 8. 高级功能") print("-" * 30) # 8.1 坐标操作 print("坐标操作:") width, height = d.window_size() print(f" 屏幕中心坐标: ({width//2}, {height//2})") print(" - 点击坐标: d.click(x, y)") print(" - 滑动坐标: d.swipe(x1, y1, x2, y2)") # 8.2 元素属性获取 print("元素属性获取:") if text_elements: first_element = text_elements[0] print(f" 第一个元素信息:") print(f" 文字: {first_element.text}") print(f" 类名: {first_element.info.get('className', 'Unknown')}") print(f" 资源ID: {first_element.info.get('resourceId', 'Unknown')}") print(f" 位置: {first_element.info.get('bounds', {})}") print(f" 可点击: {first_element.info.get('clickable', False)}") print() # 9. 实际演示 print("🎬 9. 实际演示") print("-" * 30) # 9.1 获取所有交互元素 interactive_elements = [] for element in d.xpath('//*').all(): info = element.info if (info.get('clickable', False) or info.get('focusable', False) or info.get('contentDescription', '') or info.get('text', '')): interactive_elements.append({ 'text': element.text or '', 'content_desc': info.get('contentDescription', ''), 'class_name': info.get('className', ''), 'clickable': info.get('clickable', False), 'bounds': info.get('bounds', {}) }) print(f"找到 {len(interactive_elements)} 个交互元素") print("前10个交互元素:") for i, element in enumerate(interactive_elements[:10], 1): display_text = element['text'] or element['content_desc'] or '无文字' print(f" {i:2d}. {display_text}") print(f" 类型: {element['class_name']}") print(f" 可点击: {element['clickable']}") print() print("✅ 演示完成!") print("="*60) print("📚 uiautomator2 主要能力总结:") print("1. 📸 截图 - 获取手机屏幕截图") print("2. 🔍 元素查找 - 按各种条件查找UI元素") print("3. 🎯 元素操作 - 点击、输入、滑动等操作") print("4. ⏰ 等待检测 - 等待元素出现、检测应用状态") print("5. 👆 手势操作 - 各种复杂手势操作") print("6. 📱 应用控制 - 启动、停止、管理应用") print("7. 🔧 设备控制 - 控制设备按键、获取设备信息") print("8. 🚀 高级功能 - 坐标操作、属性获取等") print("9. 🤖 自动化 - 完整的UI自动化测试能力") except Exception as e: print(f"❌ 演示失败: {e}") print("请确保:") print("1. 设备已连接 (adb devices)") print("2. 已开启USB调试") print("3. 已安装uiautomator2 (pip install uiautomator2)") if __name__ == "__main__": demo_all_capabilities()

screenshot_with_boxes.py

bash
展开代码
import uiautomator2 as u2 import json import os from datetime import datetime from PIL import Image, ImageDraw, ImageFont import random def get_screenshot_and_elements(device_id=None): """ 获取手机截图和所有元素信息 """ try: # 连接设备 if device_id: d = u2.connect(device_id) else: d = u2.connect() # 自动连接第一个设备 print(f"📱 已连接到设备: {d.info.get('productName', 'Unknown')}") # 获取截图 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") screenshot_path = f"screenshot_{timestamp}.png" d.screenshot(screenshot_path) print(f"📸 截图已保存: {screenshot_path}") # 获取所有元素(包括文字和其他可点击元素) all_elements = [] # 获取所有文字元素 for element in d.xpath('//*[@text]').all(): if element.text and element.text.strip(): element_info = { 'text': element.text.strip(), 'bounds': element.info.get('bounds', {}), 'resource_id': element.info.get('resourceId', ''), 'class_name': element.info.get('className', ''), 'content_desc': element.info.get('contentDescription', ''), 'clickable': element.info.get('clickable', False), 'enabled': element.info.get('enabled', False), 'element_type': 'text' } all_elements.append(element_info) # 获取所有可点击元素(按钮、图片等) for element in d.xpath('//*[@clickable="true"]').all(): if not element.text or not element.text.strip(): # 避免重复添加有文字的元素 element_info = { 'text': element.text or element.info.get('contentDescription', '') or '可点击元素', 'bounds': element.info.get('bounds', {}), 'resource_id': element.info.get('resourceId', ''), 'class_name': element.info.get('className', ''), 'content_desc': element.info.get('contentDescription', ''), 'clickable': element.info.get('clickable', False), 'enabled': element.info.get('enabled', False), 'element_type': 'clickable' } all_elements.append(element_info) # 保存到JSON文件 json_path = f"elements_{timestamp}.json" with open(json_path, 'w', encoding='utf-8') as f: json.dump(all_elements, f, ensure_ascii=False, indent=2) print(f"📝 元素信息已保存: {json_path}") # 打印元素统计 text_elements = [e for e in all_elements if e['element_type'] == 'text'] clickable_elements = [e for e in all_elements if e['element_type'] == 'clickable'] print(f"\n🔍 发现 {len(all_elements)} 个元素:") print(f" 📝 文字元素: {len(text_elements)} 个") print(f" 🖱️ 可点击元素: {len(clickable_elements)} 个") return screenshot_path, json_path, all_elements except Exception as e: print(f"❌ 执行失败: {e}") return None, None, [] def draw_boxes_on_screenshot(screenshot_path, elements, output_path=None): """ 在截图上绘制元素框 """ try: # 打开截图 with Image.open(screenshot_path) as img: # 创建绘图对象 draw = ImageDraw.Draw(img) # 使用指定的字体文件 try: font_path = r"D:\xiedong_dev\company_model_proxy\daily-hot-mcp\Arial-Unicode-MS.ttf" font = ImageFont.truetype(font_path, 16) print(f"✅ 成功加载字体: {font_path}") except Exception as e: print(f"⚠️ 字体加载失败: {e}") try: font = ImageFont.truetype("arial.ttf", 16) except: try: font = ImageFont.truetype("/System/Library/Fonts/Arial.ttf", 16) except: font = ImageFont.load_default() print("⚠️ 使用默认字体") # 定义颜色 colors = [ (255, 0, 0), # 红色 (0, 255, 0), # 绿色 (0, 0, 255), # 蓝色 (255, 255, 0), # 黄色 (255, 0, 255), # 紫色 (0, 255, 255), # 青色 (255, 128, 0), # 橙色 (128, 0, 255), # 紫色 ] print(f"🎨 开始绘制 {len(elements)} 个元素框...") for i, element in enumerate(elements): bounds = element.get('bounds', {}) if not bounds or not all(key in bounds for key in ['left', 'top', 'right', 'bottom']): continue # 获取坐标 left = int(bounds['left']) top = int(bounds['top']) right = int(bounds['right']) bottom = int(bounds['bottom']) # 选择颜色 color = colors[i % len(colors)] # 绘制矩形框 draw.rectangle([left, top, right, bottom], outline=color, width=3) # 准备标签文本 text = element.get('text', '') if len(text) > 20: text = text[:17] + "..." # 绘制标签背景 text_bbox = draw.textbbox((0, 0), f"{i+1}: {text}", font=font) text_width = text_bbox[2] - text_bbox[0] text_height = text_bbox[3] - text_bbox[1] # 标签位置(在框的上方) label_x = left label_y = max(0, top - text_height - 5) # 绘制标签背景 draw.rectangle([label_x, label_y, label_x + text_width + 4, label_y + text_height + 4], fill=color, outline=color) # 绘制标签文字 draw.text((label_x + 2, label_y + 2), f"{i+1}: {text}", fill=(255, 255, 255), font=font) # 保存结果 if output_path is None: base_name = os.path.splitext(screenshot_path)[0] output_path = f"{base_name}_with_boxes.png" img.save(output_path) print(f"🎨 带框截图已保存: {output_path}") return output_path except Exception as e: print(f"❌ 绘制失败: {e}") return None def load_elements_from_json(json_path): """ 从JSON文件加载元素数据 """ try: with open(json_path, 'r', encoding='utf-8') as f: elements = json.load(f) print(f"📂 从 {json_path} 加载了 {len(elements)} 个元素") return elements except Exception as e: print(f"❌ 加载JSON失败: {e}") return [] def main(): """ 主函数:截图、获取JSON、绘制框 """ print("🚀 开始截图并绘制元素框...") # 获取设备列表 try: devices = u2.device_list() print(f"📱 可用设备: {devices}") if devices: device_id = devices[0] # 使用第一个设备 print(f"使用设备: {device_id}") else: device_id = None print("使用默认设备连接") except: device_id = None print("使用默认设备连接") # 执行截图和元素提取 screenshot_path, json_path, elements = get_screenshot_and_elements(device_id) if screenshot_path and elements: print(f"\n✅ 截图和JSON获取完成!") print(f"📸 截图文件: {screenshot_path}") print(f"📝 元素数据: {json_path}") print(f"🔢 共提取 {len(elements)} 个元素") # 绘制元素框 output_path = draw_boxes_on_screenshot(screenshot_path, elements) if output_path: print(f"\n🎉 任务完成!") print(f"📸 原截图: {screenshot_path}") print(f"📝 元素数据: {json_path}") print(f"🎨 带框截图: {output_path}") else: print("❌ 绘制框失败") else: print("❌ 截图或元素获取失败") if __name__ == "__main__": main()
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!