# DroidBot 多平台适配指南 本文档介绍 DroidBot 的多平台架构设计和接口标准,帮助开发者扩展新平台支持。 ## 架构概述 DroidBot 采用抽象工厂模式,将平台无关的核心逻辑与平台特定实现分离: ``` ┌──────────────────────────────────────────────────────────┐ │ DroidBot Core │ │ (input_policy.py, input_manager.py, utg.py) │ └─────────────────────────┬────────────────────────────────┘ │ 调用抽象接口 ┌─────────────────────────▼────────────────────────────────┐ │ core/ 抽象层 │ │ AbstractDevice, AbstractDeviceState, AbstractInputEvent │ │ PlatformFactory │ └─────────────────────────┬────────────────────────────────┘ │ 平台实现 ┌─────────────────────────▼────────────────────────────────┐ │ platforms/ │ │ ├── android/ ← AndroidDevice, AndroidDeviceState │ │ ├── ios/ ← (预留) │ │ └── windows/ ← (预留) │ └──────────────────────────────────────────────────────────┘ ``` ## 核心接口 ### 1. AbstractDevice 设备抽象基类,定义平台无关的设备操作接口。 ```python class AbstractDevice(ABC): # === 必须实现的方法 === @abstractmethod def set_up(self) -> None: ... @abstractmethod def connect(self) -> bool: ... @abstractmethod def disconnect(self) -> None: ... @abstractmethod def tear_down(self) -> None: ... @abstractmethod def check_connectivity(self) -> bool: ... @abstractmethod def get_current_state(self) -> 'AbstractDeviceState': ... @abstractmethod def get_display_info(self, refresh: bool = False) -> Dict[str, Any]: ... @abstractmethod def send_event(self, event: 'AbstractInputEvent') -> bool: ... @abstractmethod def take_screenshot(self, path: str) -> bool: ... @abstractmethod def unlock(self) -> None: ... @abstractmethod def is_foreground(self) -> bool: ... @abstractmethod def start_app(self) -> bool: ... @abstractmethod def pull_back_to_app(self) -> bool: ... @property @abstractmethod def app_identifier(self) -> str: ... @abstractmethod def get_platform_name(self) -> str: ... @abstractmethod def get_device_info(self) -> Dict[str, Any]: ... @abstractmethod def create_event_from_dict(self, event_dict: Dict) -> 'AbstractInputEvent': ... ``` ### 2. AbstractDeviceState 设备状态抽象基类,定义 UI 状态信息接口。 ```python class AbstractDeviceState(ABC): # === 必须实现的属性 === @property @abstractmethod def views(self) -> List[Dict[str, Any]]: ... @property @abstractmethod def state_str(self) -> str: ... @property @abstractmethod def foreground_page(self) -> Optional[str]: ... # === 必须实现的方法 === @abstractmethod def get_possible_input(self) -> List['AbstractInputEvent']: ... @abstractmethod def to_dict(self) -> Dict[str, Any]: ... @abstractmethod def get_text_representation(self, merge_buttons: bool = False) -> tuple: ... ``` ### 3. AbstractInputEvent 输入事件抽象基类。 ```python class AbstractInputEvent(ABC): @abstractmethod def send(self, device: 'AbstractDevice') -> bool: ... @abstractmethod def to_dict(self) -> Dict[str, Any]: ... @abstractmethod def get_event_str(self, state: Optional['AbstractDeviceState'] = None) -> str: ... ``` ## 统一视图数据结构 各平台需将 UI 元素转换为统一格式: ```python { # 必需字段 "temp_id": int, # 临时 ID "bounds": [[int, int], [int, int]], # 边界框 [[left,top], [right,bottom]] "class": str, # 元素类型 # 文本相关 "text": Optional[str], # 显示文本 "content_description": Optional[str], # 无障碍描述 # 层级关系 "parent": Optional[int], # 父节点 ID "children": List[int], # 子节点 ID 列表 # 交互属性 "enabled": bool, "visible": bool, "clickable": bool, "scrollable": bool, "editable": bool, "checkable": bool, "long_clickable": bool, # 平台特有 "resource_id": Optional[str] # 平台元素标识 } ``` ## 平台映射表 | 抽象接口 | Android | iOS | Windows | |---------|---------|-----|---------| | `foreground_page` | `package/activity` | `bundleId/viewController` | `exe_path/window_title` | | `app_identifier` | package_name | bundleId | exe_path/window_class | | `resource_id` | resource_id | accessibilityIdentifier | AutomationId | ## 添加新平台步骤 ### 1. 创建平台目录 ```bash mkdir -p droidbot/platforms/ios ``` ### 2. 实现核心类 ```python # platforms/ios/__init__.py from .ios_device import IOSDevice from .ios_device_state import IOSDeviceState from .ios_input_event import IOSTouchEvent, IOSKeyEvent, ... def register_ios_platform(): from ...core.platform_factory import PlatformFactory, Platform event_classes = { 'touch': IOSTouchEvent, 'key': IOSKeyEvent, # ... } PlatformFactory.register_platform( Platform.IOS, IOSDevice, IOSDeviceState, event_classes ) # 模块导入时自动注册 register_ios_platform() ``` ### 3. 添加平台枚举 ```python # core/platform_factory.py class Platform(Enum): ANDROID = "android" IOS = "ios" # 新增 WINDOWS = "windows" # 新增 ``` ### 4. 在 platforms/__init__.py 导入 ```python from .ios import IOSDevice, IOSDeviceState ``` ## 事件类型 所有平台必须支持的事件类型: | 事件类型 | 说明 | 工厂键名 | |---------|------|---------| | Touch | 点击 | `touch` | | LongTouch | 长按 | `long_touch` | | Swipe | 滑动 | `swipe` | | Scroll | 滚动 | `scroll` | | SetText | 输入文本 | `set_text` | | Key | 按键 | `key` | | KillApp | 终止应用 | `kill_app` |