uiautomator2 核心方法

以下是 uiautomator2 核心方法 的 Markdown 代码块格式汇总(按功能分类,可直接复制使用):

uiautomator2 全量核心方法汇总(Python)

一、设备连接与初始化

import uiautomator2 as u2

# 1. 连接设备(三种方式)
d = u2.connect()  # 自动连接唯一设备
d = u2.connect("1234567890abcdef")  # 通过设备ID连接(adb devices查看)
d = u2.connect("http://192.168.1.100:7912")  # 连接远程设备(需启动atx-agent)

# 2. 连接管理
d.healthcheck()  # 检查并修复连接
d.disconnect()  # 断开连接

# 3. 获取设备信息
print(d.info)  # 设备基本信息(系统版本、分辨率等)
print(d.info.get("screenOn"))  # 判断屏幕是否亮屏

二、设备基础控制

# 1. 按键操作
d.press("home")  # 系统按键:home/back/menu/power/volume_up/volume_down
d.press(3)  # 也支持按键码(3=HOME,4=BACK)

# 2. 屏幕控制
d.screen_on()  # 点亮屏幕
d.screen_off()  # 熄灭屏幕
d.unlock()  # 解锁屏幕(支持无密码/滑动)
d.lock()  # 锁定屏幕

# 3. 屏幕方向
d.set_orientation("natural")  # 设置方向:natural/left/right/upsidedown
print(d.get_orientation())  # 获取当前方向

# 4. 系统面板
d.open_notification()  # 打开通知栏
d.open_quick_settings()  # 打开快捷设置栏

# 5. 震动
d.vibrate(duration=1000)  # 震动1秒(单位ms)

三、应用管理

# 1. 安装/卸载
d.app_install("/sdcard/test.apk")  # 安装本地APK
d.app_install("http://xxx.com/test.apk")  # 安装远程APK
d.app_uninstall("com.tencent.wechat")  # 卸载应用(包名)

# 2. 启动/停止
d.app_start("com.tencent.wechat")  # 启动应用(默认Activity)
d.app_start("com.tencent.wechat", ".ui.LoginUI")  # 指定Activity启动
d.app_stop("com.tencent.wechat")  # 停止应用
d.app_stop_all()  # 停止所有应用

# 3. 应用数据管理
d.app_clear("com.tencent.wechat")  # 清除应用数据
d.app_reset("com.tencent.wechat")  # 重置应用(卸载重装)

# 4. 应用信息查询
print(d.app_info("com.tencent.wechat"))  # 应用详情(版本、路径等)
print(d.app_list())  # 所有已安装应用包名列表
print(d.app_current())  # 当前前台应用(包名+Activity)

# 5. 等待应用状态
d.app_wait("com.tencent.wechat", timeout=10)  # 等待启动完成
d.app_wait_for_idle(timeout=10)  # 等待应用进入空闲状态

四、UI 元素定位与操作(核心)

0. 遍历集合(批量元素处理)

# 1. 获取所有匹配元素并遍历
# 使用all()方法获取所有匹配的元素,返回一个可迭代的列表
text_views = d(className="android.widget.TextView").all()
print(f"找到 {len(text_views)} 个TextView元素")

# 遍历所有元素
for i, elem in enumerate(text_views):
    try:
        text = elem.get_text()
        position = elem.center()
        print(f"元素{i}: 文本='{text}', 位置={position}")
    except Exception as e:
        print(f"元素{i}: 获取信息失败 - {e}")

# 2. 按条件过滤集合
buttons = d(className="android.widget.Button").all()
enabled_buttons = [btn for btn in buttons if btn.enabled]
print(f"启用状态的按钮数量: {len(enabled_buttons)}")

# 3. 批量操作特定索引元素
if len(text_views) > 2:
    # 点击第3个元素(索引从0开始)
    text_views[2].click()
    # 获取第1个元素的文本
    first_text = text_views[0].get_text()

# 4. 使用XPath获取并遍历元素集合
# 注意:需要先安装依赖 pip install lxml
items = d.xpath("//androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout").all()
for item in items:
    try:
        # 从每个item中获取子元素
        title = item.child(className="android.widget.TextView", index=0).get_text()
        content = item.child(className="android.widget.TextView", index=1).get_text()
        print(f"标题: {title}, 内容: {content}")
    except Exception as e:
        print(f"处理item失败: {e}")

# 5. 结合child()和sibling()方法遍历复杂层级
parent_elements = d(className="android.widget.LinearLayout", depth=2).all()
for parent in parent_elements:
    # 获取子元素集合
    children = parent.child(className="android.widget.TextView").all()
    for child in children:
        print(child.get_text())

# 6. 遍历集合时的性能优化
# 只获取可见元素以提高性能
visible_elements = d(className="android.widget.TextView", visible=True).all()
print(f"可见的TextView数量: {len(visible_elements)}")

# 7. 安全遍历(处理可能不存在的元素)
for i in range(5):  # 尝试访问前5个可能的元素
    elem = d(className="android.widget.TextView", index=i)
    if elem.exists:
        print(f"索引{i}的元素存在: {elem.get_text()}")
    else:
        print(f"索引{i}的元素不存在")

1. 元素定位(链式过滤)

# 基础定位方式
d(resourceId="com.tencent.wechat:id/btn_login")  # 资源ID(最稳定)
d(text="登录")  # 显示文本
d(description="更多选项")  # ContentDescription(图标常用)
d(className="android.widget.Button")  # 控件类名
d(packageName="com.tencent.wechat")  # 应用包名过滤
d(index=1)  # 同类型元素索引(0开始)

# 组合定位(多条件过滤)
d(text="登录", className="android.widget.Button", enabled=True)
d(resourceId="xxx").child(text="子元素")  # 子元素
d(text="登录").parent()  # 父元素
d(text="登录").sibling()  # 同级元素

# 状态过滤
d(checkable=True)  # 是否可勾选(复选框)
d(enabled=True)  # 是否启用
d(selected=True)  # 是否选中(单选框)
d(visible=True)  # 是否可见

2. 元素操作方法

# 点击操作
d(text="登录").click()  # 点击元素(超时抛异常)
d(text="登录").click_exists(timeout=10)  # 存在则点击(不抛异常)
d(text="登录").click_center()  # 点击元素中心点
d(text="登录").long_click(duration=2000)  # 长按2秒

# 文本操作
d(resourceId="com.tencent.wechat:id/et_phone").set_text("13800138000")  # 输入文本
d(resourceId="com.tencent.wechat:id/et_phone").clear_text()  # 清空文本
print(d(text="登录").get_text())  # 获取元素文本
print(d(description="更多").get_description())  # 获取描述

# 元素状态查询
print(d(text="登录").exists())  # 是否存在
print(d(text="登录").visible)  # 是否可见
print(d(text="登录").enabled)  # 是否启用
print(d(text="记住密码").is_checked())  # 是否勾选

# 元素位置与尺寸
print(d(text="登录").bound())  # 坐标范围 (x1,y1,x2,y2)
print(d(text="登录").center())  # 中心点坐标 (x,y)
print(d(text="登录").size())  # 尺寸 (width, height)

# 等待元素
d(text="登录").wait(timeout=10)  # 等待出现(超时抛异常)
d(text="加载中").wait_gone(timeout=10)  # 等待消失

# 滚动与滑动(元素内)
d(resourceId="com.tencent.wechat:id/list_view").scroll(steps=50)  # 滚动
d(resourceId="com.tencent.wechat:id/list_view").swipe("up", steps=30)  # 向上滑动
d(resourceId="com.tencent.wechat:id/list_view").fling("down")  # 快速滑动

# 批量元素操作
elements = d(className="android.widget.TextView").all()  # 获取所有匹配元素
for elem in elements:
    print(elem.get_text())
elements[0].click()  # 操作第一个元素

五、手势与坐标操作

# 1. 坐标点击/长按
d.click(500, 1000)  # 点击绝对坐标 (x,y)
d.long_click(500, 1000, duration=2000)  # 长按坐标

# 2. 滑动操作
d.swipe(300, 1500, 300, 500, steps=50)  # 从(x1,y1)滑到(x2,y2)(steps=滑动步数)
d.swipe_ext("up", scale=0.5)  # 屏幕边缘滑动(up/down/left/right,scale=滑动比例)
d.flick(300, 1500, 300, 500)  # 快速滑动(无渐变)

# 3. 双指操作(缩放)
d.pinch_in(percent=0.3, steps=30)  # 双指缩小(percent=缩放比例)
d.pinch_out(percent=0.3, steps=30)  # 双指放大

# 4. 拖拽操作
d.drag(500, 1000, 800, 1000, duration=1500)  # 拖拽(duration=总时长ms)

# 5. 连续点击
d.double_click(500, 1000)  # 双击坐标
d.triple_click(500, 1000)  # 三击坐标

六、截图与图像识别

# 1. 截图
d.screenshot("/sdcard/screen.png")  # 保存截图到设备
img = d.screenshot()  # 返回PIL图像对象
img.save("local_screen.png")  # 保存到电脑本地

# 2. 图像识别(需安装 airtest-core)
# 匹配模板图(返回坐标 (x,y),匹配度低于threshold则返回None)
pos = d.image_match("template_login_btn.png", threshold=0.8)
if pos:
    d.click(pos)

# 等待模板图出现
d.image_wait("template_success.png", timeout=10)  # 超时返回False

# 查找多个匹配项
positions = d.image_find_all("template_icon.png", threshold=0.7)

七、文件操作(设备 / 电脑互传)

# 1. 电脑 → 设备(推送文件)
d.push("local_file.txt", "/sdcard/Documents/")  # 推送文件
d.push("local_dir/", "/sdcard/Documents/", recursive=True)  # 递归推送文件夹

# 2. 设备 → 电脑(拉取文件)
d.pull("/sdcard/Documents/test.txt", "local_test.txt")  # 拉取文件
d.pull("/sdcard/Documents/", "local_dir/", recursive=True)  # 递归拉取文件夹

# 3. 设备文件管理
d.file_exists("/sdcard/test.apk")  # 判断文件是否存在
d.file_remove("/sdcard/test.apk")  # 删除文件
d.mkdir("/sdcard/MyFolder")  # 创建目录
d.rmdir("/sdcard/MyFolder", recursive=True)  # 删除目录(递归)
print(d.listdir("/sdcard/Documents"))  # 列出目录内容

八、日志与调试

# 1. 设备日志
log = d.logcat(clear=True)  # 获取adb logcat日志(clear=清空历史)
print(log[:2000])  # 打印前2000字符

# 2. UI层级导出
xml = d.dump_hierarchy()  # 导出当前UI结构(XML)
with open("ui_hierarchy.xml", "w", encoding="utf-8") as f:
    f.write(xml)

# 3. 调试模式
d.debug(True)  # 开启调试(输出详细操作日志)
d.set_fastinput_ime(False)  # 禁用快速输入(解决部分输入框兼容问题)

# 4. 软键盘控制
d.hide_keyboard()  # 隐藏软键盘
d.press("enter")  # 模拟回车键(输入框确认)

九、其他常用功能

# 1. Toast提示
d.toast.show("操作完成", duration=3000)  # 显示Toast(3秒)
print(d.toast.get_message())  # 获取最近的Toast消息

# 2. 输入框操作(无UI元素时)
d.input_text("hello uiautomator2")  # 直接输入文本(需焦点)
d.input_keyevent(66)  # 模拟按键码(66=ENTER)

# 3. 等待与延迟
d.wait(2)  # 固定延迟2秒(同time.sleep,但更稳定)
d.wait_activity(".ui.HomeUI", timeout=10)  # 等待指定Activity

# 4. Shell命令执行
result = d.shell("ls /sdcard")  # 执行adb shell命令
print(result.output)  # 命令输出
print(result.returncode)  # 退出码(0=成功)

# 5. 网络控制(需root或Android 10+)
d.set_airplane_mode(True)  # 开启飞行模式
d.set_wifi_enabled(False)  # 关闭WiFi

关键说明

  1. 所有方法需先通过 u2.connect() 初始化设备对象 d
  2. 元素定位优先使用 resourceId(唯一稳定),避免依赖 text(易变);
  3. 涉及“等待”的方法默认超时 10 秒,可通过 timeout 参数调整;
  4. 图像识别需额外安装依赖:pip install airtest-core
  5. 低版本 Android(<7.0)可能部分手势/UI功能受限,建议使用 Android 7.0+ 设备。

官方文档参考:openatx/uiautomator2

posted @ 2025-11-08 09:11  zhangdingqu  阅读(3)  评论(0)    收藏  举报