Fast Android UI Automation with ADB¶
ADB is the starting point for almost every Android automation workflow.
It can launch apps, press keys, install APKs, pull logs, and tap coordinates. It is reliable, available everywhere, and does not require root.
But raw ADB is not a high-level UI automation API.
If your script is full of commands like this:
it will work until the screen size changes, the layout shifts, or the app takes longer than expected.
For fast Android UI automation, keep ADB as the transport, but add a label-based control layer on top.
Quick answer¶
Use ADB for the device connection, but automate UI by visible labels:
hs use
hs tap "Sign in" --visible --unique
hs fill "Email" "you@example.com"
hs fill "Password" "$PASSWORD"
hs tap "Continue"
hs wait "Dashboard" --timeout 15s
Handsets uses adb forward under the hood, starts a small device-side daemon as the Android shell user, and keeps each UI action fast.
No root. No installed helper app. No coordinate spreadsheet.
What raw ADB is good at¶
Raw adb is still excellent for low-level device operations:
adb devices
adb install app.apk
adb shell am start -n com.example/.MainActivity
adb shell input keyevent BACK
adb logcat
Those commands are stable because they target Android system services, not a moving UI layout.
The problem starts when raw ADB becomes your UI selector language.
Why coordinate taps are brittle¶
This command has no semantic meaning:
It might mean "tap Continue" on one device. On another device it may tap empty space, a different button, or the keyboard.
Coordinate scripts break when:
- Screen density changes.
- Orientation changes.
- Text wraps differently.
- The keyboard appears.
- A banner pushes content down.
- A slow screen has not loaded yet.
Fast automation is not only about milliseconds. It is also about avoiding flaky retries.
Tap by text instead¶
With Handsets, the script targets what the user sees:
For unattended scripts, make ambiguity explicit:
If there are two visible Continue buttons, the command fails instead of guessing.
That is a good failure. You can fix a good failure.
Wait for state, not time¶
Fixed sleeps are another common source of slow and flaky automation.
Instead of:
use:
The script moves on as soon as the dashboard appears. If it never appears, the failure says what state was missing.
Capture screenshots only when needed¶
Screenshots are useful for debugging, but they are expensive as a default loop primitive.
Use a small screenshot when a script fails:
For agent workflows, pair the screenshot with a text UI dump:
The text dump gives you tappable labels. The screenshot gives a human visual context.
Performance shape¶
Raw ADB starts a fresh command path for each call. That is fine for occasional device commands. It gets expensive in tight UI loops.
Handsets keeps a small daemon warm on the device and talks through a forwarded socket. Typical warm calls are in the single-digit millisecond range for common actions like text lookup taps.
That matters when:
- You run many small UI actions.
- You build a mobile RPA flow.
- You drive Android from an LLM agent.
- You want quick feedback in CI smoke tests.
FAQ¶
Can ADB automate Android UI?¶
Yes, but raw ADB mostly works with coordinates and low-level input events. For robust UI automation, use a layer that can find elements by text, selector, or visible state.
Do I need root for Android UI automation with ADB?¶
No. Normal UI automation can run through USB debugging and the Android shell user. Root is not required for tapping, typing, waiting, or reading visible UI.
Is Handsets replacing ADB?¶
No. Handsets builds on ADB. It uses ADB for connection and port forwarding, then adds faster label-based UI actions.
Is this better than Appium?¶
For full cross-platform QA infrastructure, Appium is better. For Android-only CLI automation and LLM agents, Handsets is usually smaller and faster.