UI Automator: What It Is, Key Concepts, and How It Works

Author: IT Sectr Published: 2026-04-08 Reading time: 8 min

UI Automator is a framework from Google for automated UI testing of Android applications that operates at the system level and can interact with interface elements beyond a single app. Unlike Espresso, UI Automator is not tied to a specific app’s process: it can open system dialogs, the notification shade, and switch between apps. According to Google Android Developers, UI Automator uses the standard Accessibility Service to access the device’s UI tree.

Key Takeaways

  • UI Automator — a framework for cross-application UI testing on Android.
  • UiDevice — the entry point for accessing the device screen and its elements.
  • UiSelector — a mechanism for finding elements by text, class, description, and hierarchy.
  • Cross-application — tests can switch between Settings, Browser, and the tested app.
  • Accessibility Service — UI Automator uses it to read and manipulate the UI tree.

What Is UI Automator?

UI Automator is a framework for functional UI testing of Android that operates at the operating system level. It provides an API for accessing any element on the device screen, regardless of which app it belongs to — including the system status bar, permission dialogs, the home screen, and third-party apps. This makes it indispensable for testing scenarios that extend beyond a single app.

Architecturally, UI Automator uses the Accessibility Service — the same service used by TalkBack, Switch Access, and other accessibility tools. Through this service, the framework obtains the complete UI component tree of the current screen and allows performing actions on them: tapping, swiping, text input, and long pressing.

UI Automator first appeared in Android 4.3 (API 18) and has since been part of the Android Testing Support Library as Google’s official tool for cross-application testing. In AndroidX Test, it’s available as a separate artifact androidx.test.uiautomator:uiautomator version 2.3.0 (2024), which supports all Android versions from API 18.

How UI Automator Works

How it works: UI Automator is based on scanning the Accessibility tree of the current screen. When the findObject(selector) method is called, the framework traverses the View hierarchy, finds the first element matching the UiSelector conditions, and returns a UiObject — a proxy for interacting with the actual View.

UI Automator Test Lifecycle

A typical UI Automator test starts by obtaining a UiDevice instance, which represents the physical device. UiDevice provides methods for finding elements, managing button presses (Home, Back, Recent), rotating the screen, and taking screenshots. After finding an element via UiSelector, actions are performed on the UiObject.

Basic Example

In the example below, the test opens the Settings app, finds the “Battery” item by text, and taps it. UI Automator does not require launching an Activity — it works with any screen on the device, including third-party apps.

kotlin
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

// Open settings screen
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("Settings")), 2000)

// Find the "Battery" item and tap
val batteryItem = device.findObject(
    UiSelector().text("Battery")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)

UiDevice and UiSelector: Key Classes

UiDevice is the main class for interacting with the device. It provides methods for finding elements, simulating hardware button presses (Home, Back, Menu, Volume), managing power, taking screenshots, and waiting for specific screen states. UiDevice is created once per test and reused for all operations.

UiSelector is a fluent API for finding UI elements. Unlike Espresso ViewMatchers, UiSelector does not require compilation — search conditions are formed through a method chain: text(), className(), description(), resourceId(), index(). Multiple conditions are combined automatically via logical AND.

UiSelector MethodPurpose
text(String)Search by exact element text
textContains(String)Search by partial text match
resourceId(String)Search by resource ID (e.g., com.example:id/button)
className(String)Search by View class name
description(String)Search by content-description
childSelector(selector)Search for a child element within a container

Example Search with Multiple Conditions

When multiple elements on the screen share the same text, UiSelector allows combining criteria: find a container by ID, then within it — an element by text and class. This guarantees unique identification of the desired component. The childSelector method narrows the search scope to a specified container, speeding up navigation through the UI tree.

kotlin
val scrollView = device.findObject(
    UiSelector().resourceId("android:id/list")
)

// Inside the list, find the element with text "Wi-Fi"
val wifiItem = scrollView.findObject(
    UiSelector().text("Wi-Fi")
wifiItem.click()

Cross-Application Testing with UI Automator

Cross-application (inter-application) testing is the main feature for which UI Automator is chosen. The framework can switch between apps, test OAuth login via a browser, check system dialogs (permissions, app chooser), and interact with the system status bar, notification panel, and lock screen.

Testing OAuth Login

A typical cross-app test scenario: the app opens a browser for OAuth authorization, the user enters their login and password, and the browser redirects back to the app. UI Automator switches between processes, finds input fields in the browser, fills them in, and taps “Sign In”.

kotlin
// Waiting for browser to appear
device.wait(Until.hasObject(
    UiSelector().packageName("com.android.chrome")
), 5000)

// Searching for email input field in the browser
val emailField = device.findObject(
    UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"

Checking System Dialogs

UI Automator can check and dismiss system dialogs — location permissions, notifications, file access. This is critically important for testing first launch scenarios when the system sequentially requests multiple permissions. Without UI Automator, such scenarios cannot be automated because system dialogs do not belong to the app’s process.

UI Automator vs Espresso: A Comparison of Approaches

The choice between UI Automator and Espresso depends on the testing scenario. Espresso is optimized for testing a single app with automatic synchronization and minimal boilerplate. UI Automator is suited for scenarios where you need to interact with the system, browser, or multiple apps.

CriterionUI AutomatorEspresso
ScopeEntire device, multiple appsSingle app
SynchronizationManual (wait, sleep)Automatic (Idling Resource)
SpeedSlower (access via service)Faster (works within process)
System UISupports (Notifications, Quick Settings)Does not support
Search PrecisionUiSelector by attributesViewMatchers by type and hierarchy
StabilityLower (depends on timing)Higher (automatic waiting)

In practice, these frameworks are often used together: Espresso covers UI tests of the main app with high stability, while UI Automator is brought in for scenarios that extend beyond the app’s boundaries — OAuth login, system permissions, working with Share Intent. This combination provides maximum UI coverage with minimal test maintenance costs.

Setting Up UI Automator in an Android Project

Integration of UI Automator is done by adding a dependency to build.gradle. The framework is part of AndroidX Test and does not require additional manifest permissions — access to the Accessibility Service is configured automatically when the instrumented test is launched.

Gradle Dependencies

The minimal configuration includes the uiautomator artifact and the standard AndroidJUnitRunner test runner. UI Automator tests are placed in the src/androidTest directory and run on an emulator or physical device running Android API 18+.

kotlin
dependencies {
    androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
    androidTestImplementation("androidx.test.ext:junit:1.2.1")
    androidTestImplementation("androidx.test:runner:1.6.1")
}

UiDevice and Test Configuration

To obtain a UiDevice instance, InstrumentationRegistry.getInstrumentation() is used. UiDevice should be created once in the setUp() method and reused across all tests in the class to conserve device resources. It’s important to note that UiDevice is not thread-safe — all operations must be performed within the same test method thread. Creating a new UiDevice in each test incurs overhead and slows down execution. It is recommended to create UiDevice once in the beforeClass method and reuse it for all tests in the test class.

Waiting in UI Automator

Unlike Espresso, UI Automator does not have automatic synchronization. To wait for elements to appear, the UiDevice.wait(condition, timeout) method is used with an Until object: Until.findObject(selector), Until.hasObject(selector), Until.gone(selector). Without proper waits, tests become flaky due to race conditions — an element may not have appeared on the screen by the time of the search. It is recommended to set a timeout of at least 3–5 seconds for stability.

Frequently Asked Questions

How is UI Automator different from Espresso?

UI Automator operates at the Accessibility Service level and can interact with any app. Espresso works within a single app’s process and uses automatic UI thread synchronization. UI Automator is better for cross-app scenarios, while Espresso is better for stable single-app tests.

Can UI Automator be run on any device?

Yes, UI Automator works on all devices running Android API 18+. It does not require root access — it uses the standard Accessibility Service, which is activated through Instrumentation when tests are launched.

How does UI Automator find elements on the screen?

UI Automator uses the Accessibility Service to obtain the complete UI component tree of the current screen. Then UiSelector traverses this tree and finds elements by specified criteria: text, class, ID, content-description, or a combination thereof.

Does UI Automator support screenshots?

Yes, the UiDevice.takeScreenshot(storePath) method allows taking a screenshot of the current screen and saving it to a file. This is useful for debugging: when a test fails, you can save the screenshot and analyze the screen state.

Why do UI Automator tests sometimes fail without code changes?

UI Automator does not have automatic synchronization, so tests are sensitive to timing. If an animation hasn’t finished or a View hasn’t rendered yet, findObject may not find the element. The solution is to use UiDevice.wait() with a sufficient timeout.

Summary

The UI Automator toolset covers all key cross-application testing scenarios and is the standard for Android automation at the system level.

  • UI Automator — a framework for cross-application Android testing via Accessibility Service.
  • UiDevice — the entry point for accessing the device and screen elements.
  • UiSelector — a fluent API for finding elements by text, ID, class, and hierarchy.
  • Cross-app tests — OAuth login, system permissions, interaction with multiple apps.
  • Comparison with Espresso — UI Automator has broader scope but lags in stability and speed.
  • Waiting — UiDevice.wait() and Until conditions are essential for test stability.
  • API 18+ — the framework supports all devices from Android 4.3.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also