How to Automate Android Apps Without Root¶
The best Android automation script is usually not clever.
It opens the app, taps the thing a human would tap, types the thing a human would type, and waits for the screen a human would recognize.
You can do that without rooting the phone.
For many app workflows, root is a distraction. You do not need filesystem access to the app sandbox. You do not need to patch the OS. You need a reliable way to say:
That is the shape Handsets is built for.
A real login flow¶
Here is a complete no-root login script:
#!/usr/bin/env bash
set -euo pipefail
hs use
hs wait idle 200ms
hs tap "Sign in" --visible --unique --timeout 5s
hs fill "Email" "$APP_EMAIL"
hs fill "Password" "$APP_PASSWORD"
hs tap "Continue" --visible --unique
hs wait "Dashboard" --timeout 15s
That script assumes three things:
- The device is visible to
adb. - USB debugging is enabled.
- The app exposes normal Android UI nodes.
None of those require root.
Why text beats coordinates¶
Coordinate scripts look easy until the first device changes density.
That works on one screen. It is brittle everywhere else.
The better target is the thing the user sees:
Handsets resolves the label against the live Android UI tree, finds the matching node, and taps its center. If you want the script to fail when more than one thing matches, add --unique:
That is the kind of failure you can fix. A silent coordinate miss is much worse.
Waiting is part of automation¶
Most flaky Android scripts are not flaky because tapping is hard. They are flaky because waiting is sloppy.
This is fragile:
This is better:
The script waits for the state it actually needs, not for a guessed number of seconds. Fast devices move on quickly. Slow devices get the full timeout.
Use selectors when labels are not enough¶
Some screens have repeated labels: two "Continue" buttons, three "Edit" actions, a list of identical rows.
In that case, use a selector:
hs tap 'Button:has-text("Continue")' --visible --unique
hs fill 'EditText:below(TextView[text=Email])' "you@example.com"
This keeps the script readable while giving it enough structure to survive real layouts.
What this is good for¶
No-root app automation is a good fit for:
- Login and onboarding smoke tests.
- Mobile RPA flows.
- Repetitive app setup on test devices.
- LLM agents that need to drive a phone.
- Internal tools that need a small Android control surface.
It is not a replacement for every test framework. Appium has a huge ecosystem. Espresso is excellent for in-app tests. Raw adb is always available.
Handsets sits in a smaller lane: fast shell-first control of a real Android UI, with no root and no app installed on the phone.
The useful minimum¶
If you remember only one pattern, use this:
That is enough to automate a surprising amount of Android work.