Appium W3C 扩展协议完整指南:会话、设置、上下文与设备操作端点解析
【免费下载链接】appiumCross-platform automation framework for all kinds of apps, built on top of the W3C WebDriver protocol项目地址: https://gitcode.com/GitHub_Trending/ap/appium
Appium 在标准 W3C WebDriver 协议之外扩展了一组专属端点,覆盖会话管理、会话设置、上下文切换、事件日志以及设备级应用/文件/键盘/旋转操作。本文以 packages/appium/docs/zh/reference/api/appium.md 为骨架,结合 路由定义源码 与 AppiumDriver 实现 逐端点讲解请求方法、参数与响应结构,帮助读者在测试框架或脚本中直接调用这些扩展能力。
协议背景:W3C WebDriver 之上的 Appium 扩展层
Appium 服务端本质上是 W3C WebDriver 协议的一个实现,同时叠加了驱动与插件体系。除了标准端点外,Appium 扩展层提供了一批以/appium为前缀的专属路由,用于处理标准协议未覆盖的场景。这些路由集中定义在 appium.ts(会话/设置/内省类)与 appium-device.ts(设备交互类)两个路由表中,并由顶层的AppiumDriver(伞形驱动)及其承载的底层驱动(如 fake-driver、uiautomator2、xcuitest)实现。
按功能可划分为四组:
| 分组 | 端点前缀 | 覆盖能力 |
|---|---|---|
| 会话管理 | /appium/sessions、/session/:sessionId/appium/capabilities | 查看活动会话、读取会话 capabilities |
| 会话设置 | /session/:sessionId/appium/settings | 读写会话级设置项 |
| 能力内省 | /session/:sessionId/appium/commands、/extensions | 列出当前会话支持的 REST/BiDi 命令与 execute 方法 |
| 上下文 | /session/:sessionId/appium/context(s) | 切换与枚举应用上下文 |
| 事件日志 | /session/:sessionId/appium/events、/log_event | 记录与查询事件时间线 |
| 设备操作 | /session/:sessionId/appium/device/* | 应用安装/启停/状态、键盘、文件传输、旋转与方向、系统时间 |
从源码看,路由表通过payloadParams.required/optional声明各端点的参数约束,例如/session/:sessionId/appium/device/activate_app要求appId与bundleId二选一必填(写成required: [['appId'], ['bundleId']]),options可选。这种声明在请求到达命令处理器之前就完成参数校验。
会话管理端点
getAppiumSessions:枚举所有活动会话
GET /appium/sessions返回服务器上所有活动会话的信息。注意该端点默认被安全策略拦截,必须显式开启session_discovery这一 insecure feature 才能使用,详见 安全指南。
响应类型为TimestampedMultiSessionData[],即会话数据对象数组:
| Name | Description | Type |
|---|---|---|
capabilities | 会话 capabilities | object |
created | 会话创建时间(Unix 毫秒时间戳) | number |
id | 会话 ID | string |
对应实现位于 appium.ts:方法先调用this.assertFeatureEnabled(SESSION_DISCOVERY_FEATURE),随后遍历伞形驱动维护的this.sessions表,为每个活动会话组装{id, created, capabilities}。SESSION_DISCOVERY_FEATURE的常量定义见 constants.ts(值为'session_discovery')。
开启方式(以 CLI 为例):
appium --allow-insecure=session_discovery关于 insecure feature 的完整机制,可阅读 insecure-features.ts:--allow-insecure传入的条目须满足自动化名:特性名格式,*通配符表示作用于所有驱动;--relaxed-security会一次性放开全部特性,--deny-insecure则显式关闭指定项并拥有最高优先级。
getAppiumSessionCapabilities:读取会话 capabilities
GET /session/:sessionId/appium/capabilities返回创建会话时协商确定的 session capabilities。
响应为SessionCapabilities对象,包含capabilities(object,会话能力集合)一个字段。
会话设置端点
getSettings:读取当前设置
GET /session/:sessionId/appium/settings返回当前会话的全部设置项。响应Settings为“设置名 → 值”的映射对象。会话设置是驱动运行时可调的键值对,典型如ignoreUnimportantViews、waitForIdleTimeout等,详见 settings 指南。
updateSettings:更新指定设置
POST /session/:sessionId/appium/settings更新指定的会话设置,未被更新的已有设置保持不变(增量更新语义)。
参数:
| Name | Description | Type |
|---|---|---|
settings | 待更新的设置名与值组成的对象 | object |
响应为null。路由表中该端点声明payloadParams: {required: ['settings']},即settings为必填参数。
典型调用示例:
curl -X POST "$APPIUM/session/$SESSION_ID/appium/settings" \ -H 'Content-Type: application/json' \ -d '{"settings": {"waitForIdleTimeout": 1000}}'能力内省端点
这两个端点面向“会话到底支持什么”的运行时发现场景,返回值可直接用于构建通用客户端或调试面板。类型定义可参考 基于驱动命令的类型声明,实现位于 inspector-commands.ts。
listCommands:列出会话支持的 REST 与 BiDi 命令
GET /session/:sessionId/appium/commands返回当前会话支持的 URL 端点与 WebDriver BiDi 命令,并按来源分组。响应类型为ListCommandsResponse,结构大致为:
rest:REST 端点信息,按base(Appium 基础命令)、driver(驱动特有命令)、plugins(插件注册的命令)分组;bidi:BiDi 命令,同样按base/driver/plugins分组,每个命令项包含命令名、是否弃用(deprecated)、说明(info)及参数声明(params,含 required 标记)。
从实现看,listCommands在传入sessionId时会通过this.driverForSession(sessionId)与this.pluginsForSession(sessionId)动态取出该会话绑定的驱动类与插件类,再聚合其newMethodMap、newBidiCommands;不传 sessionId 时仅返回基础层信息。
listExtensions:列出会话支持的 execute 方法
GET /session/:sessionId/appium/extensions返回当前会话支持的 execute 方法(即通过driver.executeScript/ W3C 的execute能力调用的扩展方法),按来源分组为driver(驱动特有)与plugins(插件注册)。响应类型为ListExtensionsResponse,与listCommands的 REST 部分结构一致。实现中聚合的是驱动类与插件类的executeMethodMap。
上下文端点
上下文(context)用于区分混合应用中不同的运行环境,典型如原生视图与 WebView。三个端点组成完整的上下文查询/切换闭环:
getCurrentAppiumContext:读取当前上下文
GET /session/:sessionId/appium/context返回当前活动上下文的名称(string)。
setAppiumContext:设置活动上下文
POST /session/:sessionId/appium/context将指定上下文设为活动上下文。
参数:
| Name | Description | Type |
|---|---|---|
name | 要激活的上下文名称 | string |
响应为null。路由表声明name必填。
getAppiumContexts:枚举可用上下文
GET /session/:sessionId/appium/contexts返回所有可用上下文的名称数组(string[])。
事件日志端点
事件日志用于记录会话生命周期内发生的里程碑事件,为耗时分析与性能诊断提供时间线数据,相关概念可参考 event-timing 指南。
getLogEvents:获取会话事件历史
POST /session/:sessionId/appium/events返回当前会话已记录的事件。默认情况下只有驱动命令执行会被记录;驱动或插件可定义额外事件类型,客户端也可通过logCustomEvent端点主动写入事件。
参数:
| Name | Description | Type |
|---|---|---|
type? | 用于过滤返回事件的一个或多个类型 | string 或 array<string> |
响应为EventHistory对象,键对应事件类型。事件分为三类,示例如下:
{ "commands": [ { "cmd": "getStatus", "startTime": 1756887645447, "endTime": 1756887645454 } ], "driverevent": [1756887645454], "namespace:event": [1756887645454] }commands键始终存在,值为对象数组,每个对象含三个字段:cmd(执行的命令名)、startTime(命令开始时间,Unix 毫秒)、endTime(命令结束时间,Unix 毫秒);- 其他非命名空间键为驱动/插件实现特有,值是事件时间(Unix 毫秒)数组;
- 命名空间键(形如
namespace:event)可通过logCustomEvent写入,也可由驱动/插件直接提供,值同样是事件时间数组。
实现位于 event.ts:getLogEvents在未传type或传入空值时返回完整事件历史,否则只返回与指定类型匹配的条目。
logCustomEvent:写入自定义事件
POST /session/:sessionId/appium/log_event记录一个自定义事件,随后可通过getLogEvents检索。
参数:
| Name | Description | Type |
|---|---|---|
vendor | 用于事件前缀的命名空间(供应商)名 | string |
event | 事件名 | string |
响应为null。实现中该方法将vendor与event拼接为vendor:event形式写入事件日志(event.ts),因此最终事件键呈现为命名空间风格。vendor、event均为必填参数。
设备操作端点(应用生命周期)
以下端点均以/session/:sessionId/appium/device/为前缀。应用标识参数appId(Android 包名)与bundleId(iOS Bundle ID)在源码路由表中均为“二选一必填”约束。options为驱动特有选项,含义由具体驱动定义。
activateApp:激活应用
POST /session/:sessionId/appium/device/activate_app将应用带到前台并激活。
| Name | Description | Type |
|---|---|---|
appId或bundleId | 应用标识(Android 包名 / iOS Bundle ID) | string |
options? | 驱动特有的启动选项 | unknown |
响应为void。
terminateApp:终止应用
POST /session/:sessionId/appium/device/terminate_app终止正在运行的应用。
| Name | Description | Type |
|---|---|---|
appId或bundleId | 应用标识 | string |
options? | 驱动特有的终止选项 | unknown |
响应为void。
queryAppState:查询应用状态
POST /session/:sessionId/appium/device/app_state返回应用当前状态对应的整数:
| Number | App State |
|---|---|
0 | 未安装(Not installed) |
1 | 未运行(Not running) |
2 | 后台挂起(Running in background suspended) |
3 | 后台运行(Running in background) |
4 | 前台运行(Running in foreground) |
参数为appId或bundleId,响应为number。
installApp:安装应用
POST /session/:sessionId/appium/device/install_app| Name | Description | Type |
|---|---|---|
appPath | 应用文件的绝对本地路径或 URL | string |
options? | 驱动特有的安装选项 | unknown |
响应为void。appPath必填。
removeApp:卸载应用
POST /session/:sessionId/appium/device/remove_app| Name | Description | Type |
|---|---|---|
appId或bundleId | 应用标识 | string |
options? | 驱动特有的卸载选项 | unknown |
响应为boolean,true表示卸载成功,否则为false。
isAppInstalled:检查应用是否已安装
POST /session/:sessionId/appium/device/app_installed参数为appId或bundleId,响应为boolean:已安装返回true,否则false。
设备操作端点(键盘、文件与系统)
hideKeyboard:隐藏虚拟键盘
POST /session/:sessionId/appium/device/hide_keyboard尝试隐藏被测设备上的虚拟键盘,参数均为可选:
| Name | Description | Type |
|---|---|---|
key? | 用于隐藏键盘的按键文本 | string |
keyCode? | 触发隐藏的键码 | string |
keyName? | 用于隐藏键盘的键名 | string |
strategy? | 驱动特有的隐藏策略名 | string |
响应为boolean:操作成功返回true,否则false。需要注意部分平台可能永远不会返回false(例如该平台对“隐藏”操作总是静默成功)。
isKeyboardShown:检查键盘是否显示
GET /session/:sessionId/appium/device/is_keyboard_shown响应为boolean:键盘显示返回true,否则false。
pushFile:向设备写入文件
POST /session/:sessionId/appium/device/push_file| Name | Description | Type |
|---|---|---|
data | 写入文件的 Base64 编码数据 | string |
path | 设备上要创建文件的远程路径 | string |
响应为void。path与data均必填。
pullFile:从设备拉取文件
POST /session/:sessionId/appium/device/pull_file| Name | Description | Type |
|---|---|---|
path | 设备上文件的远程路径 | string |
响应为string,即文件内容的 Base64 编码。
pullFolder:拉取目录压缩包
POST /session/:sessionId/appium/device/pull_folder| Name | Description | Type |
|---|---|---|
path | 设备上目录的远程路径 | string |
响应为string,即目录内容压缩后的 Base64 编码 ZIP。
getAppiumRotation / setAppiumRotation:空间旋转
GET /session/:sessionId/appium/device/rotation POST /session/:sessionId/appium/device/rotationgetAppiumRotation返回设备当前空间朝向,响应为Rotation对象:
| Name | Description | Type |
|---|---|---|
x | 设备绕 X 轴旋转的角度(度) | number |
y | 设备绕 Y 轴旋转的角度(度) | number |
z | 设备绕 Z 轴旋转的角度(度) | number |
setAppiumRotation以同样三个参数(x、y、z,均必填)设置朝向,响应为null。这一端点常用于平板、折叠屏等支持多轴旋转的设备。
getAppiumOrientation / setAppiumOrientation:屏幕方向
GET /session/:sessionId/appium/device/orientation POST /session/:sessionId/appium/device/orientationgetAppiumOrientation返回当前屏幕方向,响应为string,取值PORTRAIT或LANDSCAPE。
setAppiumOrientation设置屏幕方向,参数:
| Name | Description | Type |
|---|---|---|
orientation | 新方向,支持PORTRAIT或LANDSCAPE | string |
响应为null。
getDeviceTime:获取设备系统时间
POST /session/:sessionId/appium/device/system_time返回被测设备的当前系统时间。注意在路由源码中该路径同时注册了GET与POST两种方法(见 appium-device.ts),POST支持可选参数format。
| Name | Description | Type | Default |
|---|---|---|---|
format? | 返回时间戳使用的格式 | string | YYYY-MM-DDTHH:mm:ssZ |
响应为string(设备时间字符串)。该端点常用于脚本中校验设备时钟偏差或与宿主机器时间对齐。
端点总览与调用建议
| 端点 | 方法 | 核心参数 | 返回值 |
|---|---|---|---|
/appium/sessions | GET | 无(需session_discovery特性) | TimestampedMultiSessionData[] |
/session/:sessionId/appium/capabilities | GET | 无 | SessionCapabilities |
/session/:sessionId/appium/settings | GET / POST | settings(POST 必填) | Settings/null |
/session/:sessionId/appium/commands | GET | 无 | ListCommandsResponse |
/session/:sessionId/appium/extensions | GET | 无 | ListExtensionsResponse |
/session/:sessionId/appium/context(s) | GET / POST | name(POST 必填) | string/string[]/null |
/session/:sessionId/appium/events | POST | type? | EventHistory |
/session/:sessionId/appium/log_event | POST | vendor、event(必填) | null |
/session/:sessionId/appium/device/activate_app | POST | appId或bundleId | void |
/session/:sessionId/appium/device/terminate_app | POST | appId或bundleId | void |
/session/:sessionId/appium/device/app_state | POST | appId或bundleId | number(0–4) |
/session/:sessionId/appium/device/install_app | POST | appPath | void |
/session/:sessionId/appium/device/remove_app | POST | appId或bundleId | boolean |
/session/:sessionId/appium/device/app_installed | POST | appId或bundleId | boolean |
/session/:sessionId/appium/device/hide_keyboard | POST | key?/keyCode?/keyName?/strategy? | boolean |
/session/:sessionId/appium/device/is_keyboard_shown | GET | 无 | boolean |
/session/:sessionId/appium/device/push_file | POST | data、path(必填) | void |
/session/:sessionId/appium/device/pull_file | POST | path(必填) | string(Base64) |
/session/:sessionId/appium/device/pull_folder | POST | path(必填) | string(Base64 ZIP) |
/session/:sessionId/appium/device/rotation | GET / POST | x/y/z(POST 必填) | Rotation/null |
/session/:sessionId/appium/device/orientation | GET / POST | orientation(POST 必填) | string/null |
/session/:sessionId/appium/device/system_time | GET / POST | format? | string |
实际使用时有几点建议:
- 会话级端点都要求有效的
sessionId,只有/appium/sessions是无会话端点(且受session_discovery特性保护); appId/bundleId二选一是路由层的硬性校验(required: [['appId'], ['bundleId']]),不要同时省略;- 设备操作的具体行为依赖驱动实现:同一个端点在不同驱动(如 uiautomator2 与 xcuitest)下的选项与语义可能有差异,
options参数请以对应驱动文档为准;仓库内置的 fake-driver 的 general.ts 提供了这些命令的最小可运行实现,可作为阅读参考; - 能力内省端点适合在编写通用框架时动态探测目标会话支持的命令集与 execute 方法,避免硬编码协议表。
借助以上端点,测试框架可以在标准 WebDriver 能力之外完成会话审计、设置调优、混合应用上下文切换、应用生命周期管理、设备文件交换与事件时间线分析等端到端任务。若需进一步了解 capabilities、settings 与 execute methods 的定义,可继续阅读 caps.md、settings.md 与 execute-methods.md。
【免费下载链接】appiumCross-platform automation framework for all kinds of apps, built on top of the W3C WebDriver protocol项目地址: https://gitcode.com/GitHub_Trending/ap/appium
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考