AutoGLMPhone03-adb模块

AutoGLMPhone03-adb模块

模块一:当前文件夹核心内容梳理

1.1 核心知识极简概括

  • 统一设备连接管理:封装ADB连接逻辑,提供对USB/WiFi/远程设备的统一连接、断开和状态查询接口
  • 设备交互抽象层:屏蔽底层ADB命令复杂性,提供直观的设备控制方法如点击、滑动、返回等操作
  • 专用输入系统:基于ADB Keyboard实现可靠的文本输入机制,支持中文等复杂字符输入
  • 视觉反馈采集:提供屏幕截图功能,支持敏感画面检测及fallback机制
  • 模块化架构设计:各功能组件解耦合,便于独立维护和扩展

1.2 子知识扩展

统一设备连接管理
  1. 连接类型识别:自动区分USB、WiFi和远程连接类型,根据device_id格式判断连接方式
  2. 连接状态跟踪:实时监控设备连接状态,支持单设备或多设备环境下的精确识别
  3. TCP/IP调试支持:提供enable_tcpip方法启用无线调试,支持自定义端口配置
  4. 异常处理机制:内置超时控制和异常捕获,确保网络不稳定的环境下连接可靠性
  5. IP地址发现:自动探测设备在网络中的IP地址,简化无线连接配置过程

是 否 ADBConnection connect disconnect list_devices enable_tcpip 连接成功? 返回True 返回False 解析设备信息 构建DeviceInfo列表

设备交互抽象层
  1. 坐标操作封装:将tap、swipe等坐标相关操作封装为简单函数调用,隐藏ADB命令细节
  2. 应用生命周期管理:提供launch_app、get_current_app等方法控制应用启动和状态查询
  3. 延时策略配置:每种操作可配置延时时间,默认使用timing配置,支持动态调整
  4. 多设备支持:所有操作均支持device_id参数,适配多设备并行测试场景
  5. 系统按键模拟:封装常用系统按键如home、back等,提供一致的操作接口

用户代码 device.py ADB命令 tap(x, y) adb shell input tap x y 执行结果 None(带delay) 用户代码 device.py ADB命令

专用输入系统
  1. ADB Keyboard集成:依赖ADB Keyboard实现稳定文本输入,避免原生输入法干扰
  2. 输入法切换机制:自动检测并切换至ADB Keyboard,操作完成后恢复原输入法
  3. Base64编码传输:采用Base64编码传输文本,确保特殊字符正确输入
  4. 预热与清理机制:输入前后添加适当延时,确保输入法切换和文本输入稳定性
  5. 兼容性保障:提供clear_text方法清除输入框内容,配合type_text使用更可靠

否 是 type_text 检测当前输入法 是ADB Keyboard? 切换到ADB Keyboard 直接输入 Base64编码文本 广播ADB_INPUT_B64事件

视觉反馈采集
  1. 截图完整流程:远程截图→拉取至本地→编码为Base64,提供完整的图像数据流
  2. 敏感画面处理:检测截图失败场景(如支付界面),返回黑色占位图并标记敏感属性
  3. 内存优化策略:使用临时文件和BytesIO减少内存占用,及时清理临时资源
  4. 尺寸信息保留:不仅返回图像数据,同时保留宽高信息便于UI分析
  5. 异常容错机制:各类异常情况下均能返回有效Screenshot对象,保证流程不中断

是 否 get_screenshot 执行远程截图 拉取截图到本地 文件存在? 读取并编码图像 创建fallback截图 清理临时文件 返回Screenshot对象

模块化架构设计
  1. 功能职责分离:connection、device、input、screenshot各自专注特定领域功能
  2. 统一导出接口:通过__init__.py统一暴露所有公共接口,简化外部引用
  3. 依赖注入友好:各模块设计考虑了可测试性,便于mock和单元测试
  4. 配置中心化:通过timing配置集中管理各类操作延时,便于统一调整
  5. 扩展性预留:采用类和函数式混合设计,方便新增功能和定制化需求

init.py connection.py device.py input.py screenshot.py apps.py timing.py

1.3 知识点详细说明

统一设备连接管理

初始化流程

ADBConnection类是整个连接管理的核心,通过adb_path参数指定ADB可执行文件路径,默认为"adb"。初始化过程中不进行实际连接操作,仅保存配置参数。这种懒加载设计避免了不必要的连接尝试,提高初始化性能。

设备发现机制

list_devices方法通过执行adb devices -l命令获取所有连接设备信息,并解析输出构建DeviceInfo对象列表。解析过程中会根据device_id格式判断连接类型:

  • 包含":"的为REMOTE类型(网络连接)
  • 包含"emulator"的为USB类型(模拟器)
  • 其余默认为USB类型(物理设备)

此外还会解析设备型号(model)等附加信息,为上层应用提供更多设备上下文。

连接管理策略

connect方法支持TCP/IP连接,会自动处理端口默认值(5555)并验证连接结果。支持超时控制,默认10秒超时防止长时间阻塞。

disconnect方法可以断开指定设备或所有设备连接,保持连接环境清洁。

无线调试支持

enable_tcpip方法实现在USB连接设备上启用TCP/IP调试功能。这是无线连接的前提条件,需要设备先通过USB连接并在设备上执行adb tcpip命令。

设备信息服务

提供了多种设备信息服务方法:

创建ADBConnection实例 connect()成功 disconnect()调用 reconnect enable_tcpip()成功 无线连接建立 disconnect Initialized Connected Disconnected TCPIP_Enabled Wireless_Connected 连接状态 get_device_ip() 运行应用 截图 Device_Listed IP_Detected App_Running Screenshot_Captured

设备交互抽象层

坐标操作实现

设备交互层主要封装了各类触摸和按键操作,这些操作通过调用ADB shell命令实现。例如tap方法实际执行的是adb shell input tap x y命令。

为了适应不同性能的设备和应用响应速度,几乎所有操作都支持delay参数,默认使用timing配置中的相应值。这种设计既保证了操作的可靠性,又提供了灵活的性能调优手段。

滑动操作优化

swipe方法除了基本的起点终点参数外,还支持duration_ms参数控制滑动持续时间。当未指定时,会根据滑动距离自动计算合适的持续时间,范围限定在1000-2000毫秒之间,确保滑动操作自然流畅。

应用管理机制

launch_app方法通过应用名称查找对应的包名,然后使用monkey命令启动应用。这种方法比直接使用am命令启动Activity更加稳定,因为它会自动寻找应用的Launcher Activity。

get_current_app通过解析dumpsys window输出识别当前前台应用,依赖apps.py中维护的应用名称与包名映射关系。

多设备环境支持

所有设备操作方法都支持device_id参数,通过_get_adb_prefix函数构建带设备标识的ADB命令前缀。这种设计使得同一套代码可以轻松适配单设备和多设备环境。
是 否 设备操作函数 device_id是否指定 adb -s {device_id} ... adb ... 执行ADB命令

专用输入系统

ADB Keyboard集成原理

type_text方法依赖ADB Keyboard实现文本输入,通过发送广播事件ADB_INPUT_B64传递Base64编码的文本内容。这种方式绕过了系统输入法,直接向应用发送文本,避免了输入法候选词、联想等功能的干扰。

输入法切换流程

detect_and_set_adb_keyboard方法首先获取当前默认输入法,如果不是ADB Keyboard则进行切换。切换后会执行一次空输入预热键盘,确保后续输入操作正常工作。

restore_keyboard用于恢复原来的输入法,通常在完成文本输入操作后调用,保持设备环境的一致性。

文本编码处理

为确保各种字符都能正确传输,文本在发送前会经过Base64编码。这解决了特殊字符、中文等在命令行传输中可能出现的编码问题。

时序控制

输入操作涉及多个步骤:切换输入法→输入文本→恢复输入法,每个步骤都需要适当的延时确保操作完成。配置项如keyboard_switch_delaytext_input_delay等控制各环节的时间间隔。
用户代码 input.py ADB Keyboard Android系统 detect_and_set_adb_keyboard() 查询当前输入法 返回输入法信息 设置为ADB Keyboard 激活ADB Keyboard 发送空文本预热 确认激活 type_text("测试文本") Base64编码 发送ADB_INPUT_B64广播 向焦点控件输入文本 restore_keyboard(original_ime) 恢复原始输入法 用户代码 input.py ADB Keyboard Android系统

视觉反馈采集

截图流程详解

get_screenshot方法通过三个步骤完成截图:

  1. 在设备上执行screencap命令生成截图文件
  2. 将截图文件拉取到本地临时目录
  3. 读取本地文件并转换为Base64编码

敏感画面处理

Android系统对于某些敏感界面(如支付密码输入界面)会阻止截图操作。当截图失败时,会返回一个黑色占位图,并将is_sensitive标志设为True,提醒上层应用注意隐私保护。

资源管理策略

使用uuid生成唯一临时文件名避免冲突,操作完成后立即删除临时文件释放磁盘空间。使用BytesIO在内存中处理图像数据,避免频繁的磁盘IO操作。

数据结构设计

Screenshot数据类包含base64_data、width、height和is_sensitive四个字段,提供了完整的截图信息。其中is_sensitive字段特别重要,它标识了截图是否涉及敏感内容。

跨平台兼容性

通过PIL库处理图像,屏蔽了不同平台间图像格式的差异。Base64编码确保了数据在网络传输中的兼容性。
是 否 get_screenshot调用 远程截图 截图成功? 拉取截图文件 创建黑色占位图 设置is_sensitive=true 读取并编码图像 获取图像尺寸 清理临时文件 构造Screenshot对象

模块化架构设计

模块划分原则

整个adb模块按照功能划分为四个核心模块:

这种划分遵循单一职责原则,每个模块只关注特定领域的功能。

接口统一暴露

通过init.py文件统一导入并暴露所有公共接口,外部使用者只需引入phone_agent.adb即可访问全部功能,无需关心内部模块结构。

依赖管理

各模块间的依赖关系清晰,主要依赖关系包括:

  • device.py依赖apps.py获取应用包名映射
  • 多个模块依赖timing.py获取时序配置
  • 所有模块都使用subprocess执行ADB命令

配置中心化

通过timing.py集中管理所有时序相关配置,支持环境变量覆盖,便于根据不同设备性能和网络状况调整操作延时。

可测试性设计

各模块函数设计考虑了可测试性,支持device_id参数便于在多设备环境中进行精确控制,也为mock测试提供了便利。
外部使用者 init.py connection.py device.py input.py screenshot.py apps.py timing.py subprocess

模块二:核心代码逻辑

2.1 核心类/方法速查表

类/方法名 定位(文件:行号) 输入输出 使用场景示例(1句话) 调试提示(如:断点打在哪)
ADBConnection connection.py:47 adb_path → ADB连接管理器实例 初始化连接管理器以控制多个设备 __init__方法确认adb_path是否正确
connect connection.py:57 address, timeout → (bool, str) 连接到远程设备以进行无线控制 在命令执行前检查address格式
list_devices connection.py:128 无 → DeviceInfo列表 获取所有连接设备列表以选择目标设备 在解析line处检查输出格式
tap device.py:48 x, y, device_id, delay → None 在屏幕上指定坐标点击按钮或元素 在subprocess.run调用处确认命令
swipe device.py:117 start_x, start_y, end_x, end_y, duration_ms, device_id, delay → None 在屏幕上滑动以滚动列表或切换页面 在duration_ms计算处验证逻辑
type_text input.py:12 text, device_id → None 在输入框中输入用户名或密码 在encoded_text处检查编码结果
get_screenshot screenshot.py:33 device_id, timeout → Screenshot对象 获取屏幕截图用于视觉分析或验证操作结果 在temp_path生成处确认路径有效性

2.2 最小复现示例(伪代码)

python 复制代码
# ①依赖注入
import subprocess
from dataclasses import dataclass
from typing import Optional

# 模拟配置
class MockTimingConfig:
    default_tap_delay = 1.0

TIMING_CONFIG = MockTimingConfig()

# ②关键调用
def _get_adb_prefix(device_id: Optional[str]) -> list:
    """获取ADB命令前缀"""
    if device_id:
        return ["adb", "-s", device_id]
    return ["adb"]

def tap(x: int, y: int, device_id: str = None):
    """点击屏幕指定位置"""
    # 关键调用:执行ADB命令
    adb_prefix = _get_adb_prefix(device_id)
    subprocess.run(
        adb_prefix + ["shell", "input", "tap", str(x), str(y)], 
        capture_output=True
    )
    # 延时等待操作生效
    import time
    time.sleep(TIMING_CONFIG.default_tap_delay)

def get_screenshot(device_id: str = None) -> dict:
    """获取屏幕截图"""
    import tempfile
    import os
    import uuid
    from PIL import Image
    import base64
    from io import BytesIO
    
    # 创建临时文件路径
    temp_path = os.path.join(tempfile.gettempdir(), f"screenshot_{uuid.uuid4()}.png")
    adb_prefix = _get_adb_prefix(device_id)
    
    # 执行截图命令
    subprocess.run(
        adb_prefix + ["shell", "screencap", "-p", "/sdcard/tmp.png"],
        capture_output=True
    )
    
    # 拉取截图文件
    subprocess.run(
        adb_prefix + ["pull", "/sdcard/tmp.png", temp_path],
        capture_output=True
    )
    
    # 读取并编码图像
    img = Image.open(temp_path)
    width, height = img.size
    
    buffered = BytesIO()
    img.save(buffered, format="PNG")
    base64_data = base64.b64encode(buffered.getvalue()).decode("utf-8")
    
    # 清理临时文件
    os.remove(temp_path)
    
    # 返回Screenshot对象信息
    return {
        "base64_data": base64_data,
        "width": width,
        "height": height,
        "is_sensitive": False
    }

# ③断言验证
if __name__ == "__main__":
    # 模拟点击操作
    tap(500, 500)  # 点击屏幕中心
    
    # 获取截图验证操作结果
    screenshot = get_screenshot()
    
    # 验证截图数据完整性
    assert "base64_data" in screenshot
    assert screenshot["width"] > 0
    assert screenshot["height"] > 0
    assert isinstance(screenshot["base64_data"], str)
    
    print("✅ ADB操作模块核心功能验证通过")
相关推荐
今晚务必早点睡8 小时前
MySQL 新手避坑指南:安装、区分、检查一步到位
数据库·mysql·adb
EdisonZhou8 小时前
MAF快速入门(7)工作流的状态共享
llm·aigc·agent·.net core
洛阳泰山8 小时前
快速上手 MaxKB4J:开源企业级智能知识库系统在 Sealos 上的完整部署指南
java·开源·llm·agent·rag
我的offer在哪里18 小时前
mysql修改密码
adb
编程小Y18 小时前
MySQL 与 MCP 集成全解析(核心原理 + 实战步骤 + 应用场景)
数据库·mysql·adb
青衫客361 天前
浅谈 LightRAG —— 把“结构理解”前移到索引阶段的 RAG 新范式
大模型·llm·rag
破烂pan1 天前
模型推理加速技术全景解析:从基础优化到前沿创新
llm·模型加速
visnix1 天前
AI大模型-LLM原理剖析到训练微调实战(第二部分:大模型核心原理与Transformer架构)
前端·llm
智泊AI1 天前
重磅!小米刚刚发布新模型MiMo-V2-Flash开源了!
llm