[分享创造] [开源] 用 Rust 写了一个 Android 高性能自动化 CLI

handsets —— 用 Rust 写的 Android 高性能自动化 CLI 。 设计 客户端 Rust 单二进制 daemon 是一个 ~几百 KB 的 jar ,通过 adb forward 跑在设备 shell UID 下,无需 root 也无需装 APK 通信走长度前缀的二进制帧 性能 ...
[分享创造] [开源] 用 Rust 写了一个 Android 高性能自动化 CLI
[分享创造] [开源] 用 Rust 写了一个 Android 高性能自动化 CLI

handsets —— 用 Rust 写的 Android 高性能自动化 CLI 。

设计

  • 客户端 Rust 单二进制
  • daemon 是一个 ~几百 KB 的 jar ,通过 adb forward 跑在设备 shell UID 下,无需 root 也无需装 APK
  • 通信走长度前缀的二进制帧

性能

handsets adb shell uiautomator2 Appium 单次调用延迟 2-7ms 40-700ms 30-100ms 100-500ms

adb shell input tap 之所以慢且不稳定,是因为它走 injectInputEvent(ev, sync=true),sync 模式会阻塞到 InputDispatcher 处理完事件 —— 当 UI 线程在做动画或 layout 的时候,sync 排在队尾等。实测最长 tap 尖峰 2.3 秒。

handsets 默认走 AccessibilityNodeInfo.ACTION_CLICK,绕开 InputDispatcher ,直接触发 widget 的 OnClickListener ,p99 ~50ms 。OnTouchListener-only 的自定义 View 会 fallback 到 gesture path 。

hs ui 的输出格式

不是 XML accessibility dump ,而是 verb-led 表格:

  tap   ImageButton  "返回"   #back_btn   98,243
  fill  EditText     "邮箱"   #email_et   540,540
  fill  EditText     "密码"   #pwd_et     540,640  [password]
  tap   Button       "登录"   #login_btn  540,860

每行给出建议动词、selector 、坐标、flag 。LLM agent 直接读这张表就能下一步,token 占用比 XML 少一个数量级。

登录流程示例

  hs use                          # 连设备、起 daemon
  hs ui                           # 看一眼当前屏幕
  hs fill 邮箱 user@example.com   # 自动匹配邮箱 EditText
  hs fill 密码 hunter2
  hs tap 登录                     # 走 ACTION_CLICK
  hs wait 欢迎                    # 阻塞至目标文本出现

Python 绑定(pip install handsets):

  from handsets import Session

  with Session.use() as s:
      s.fill("邮箱", "user@example.com")
      s.fill("密码", "hunter2")
      s.tap("登录")
      s.wait("欢迎")

selector 兼容 CSS + Playwright 风格:

  hs find 'Button:has-text("Sign in")'
  hs find 'EditText:below(TextView[text=Email])'
  hs find 'Button:near(ImageView, 200)'

链接

来源: v2ex查看原文