Skip to content

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:

adb shell input tap 540 860
sleep 5
adb shell input text user@example.com

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:

adb shell input tap 540 860

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:

hs tap "Continue"

For unattended scripts, make ambiguity explicit:

hs tap "Continue" --visible --unique --timeout 5s

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:

adb shell input tap 540 860
sleep 10

use:

hs tap "Continue"
hs wait "Dashboard" --timeout 15s

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:

hs see --size 768 /tmp/android-failure.jpg

For agent workflows, pair the screenshot with a text UI dump:

hs ui > /tmp/ui.txt
hs see --size 768 /tmp/screen.jpg

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.