LetItDo: Building an On‑Device Android Voice Agent with Go and Accessibility
Enable WRITE_SECURE_SETTINGS via ADB and implement a watchdog WorkManager to keep the accessibility service alive on OEM devices.
Enable WRITE_SECURE_SETTINGS via ADB and implement a watchdog WorkManager to keep the accessibility service alive on OEM devices.
Summary
LetItDo is an Android voice agent that runs entirely on-device using a Go‑compiled libcrush.so bundled with AutoX, eliminating the need for a USB cable or ADB at runtime. The architecture follows a cascade interaction layer: a11y text, substring, fuzzy, OCR, and vision, mirroring the approach of Perplexity Comet and other research agents. A bug in WhatsApp’s chat list—where the text node was not clickable—was fixed by walking up the accessibility tree to the first clickable ancestor, a pattern used by Comet.
Another bug involved getBoundsInScreen returning null because the method was called without an out‑parameter; the fix was to pass a Rect. OEM battery managers on devices like Vivo, Xiaomi, Oppo, OnePlus, and Huawei kill the accessibility service, so the author grants WRITE_SECURE_SETTINGS via ADB once at install and runs a WorkManager watchdog every 15 minutes to restart the service if needed.
Key changes
- LetItDo runs on-device using Go‑compiled libcrush.so with AutoX, no USB or ADB at runtime
- Cascade interaction layer: a11y text, substring, fuzzy, OCR, vision
- Bug: WhatsApp chat list clickable=false; fixed by walking up to first clickable ancestor
- Bug: getBoundsInScreen returned null; corrected by passing a Rect
- OEM battery kill requires WRITE_SECURE_SETTINGS via ADB and watchdog WorkManager every 15 minutes
- AccessibilityService.performAction(ACTION_CLICK) used for click actions
- LLM integration uses external API; only writes to device
- On-device runtime reduces latency and cost