Appium UiAutomator2 Driver

repository·master·Indexed 21 days ago

https://github.com/appium/appium-uiautomator2-driver

A test automation framework for Android devices supporting native, hybrid, and mobile web apps on emulators and real devices. It leverages Google's UiAutomator framework via the W3C WebDriver protocol. The driver includes comprehensive capabilities for session parameters, app and activity management, ADB interaction, AVD configuration, and Web context/Chromedriver integration. It supports various element location strategies and partial W3C BiDi Protocol support starting from version 3.7.10.

Tokens
47K
Snippets
143
Records
231
Agent score
74%

What's inside appium-uiautomator2-driver

  1. Use UiScrollable to find elements and scroll into view

    master

    The driver supports UiScrollable to handle elements that are not currently visible on the screen. You can use UiScrollable to find a scrollable container and then use methods like getChildByText or scrollIntoView to locate specific elements.

    • getChildByText: Finds a child element within a scrollable container by its text.
    • scrollIntoView: Scrolls the container until the specified UiSelector is visible and returns that element.
    # Find a TextView with text "Tabs" inside a scrollable container
    element = find_element(:uiautomator, 'new UiScrollable(new UiSelector().scrollable(true).instance(0)).getChildByText(new UiSelector().className("android.widget.TextView"), "Tabs")')
    
    # Scroll to an element matching a UiSelector and return it
    element = find_element(:uiautomator, 'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("WebView").instance(0));')
  2. Configure UiAutomator2 driver-specific settings

    master

    The UiAutomator2 driver supports the Appium Settings API, allowing you to tune driver behavior via specific configuration keys. These settings can be used to modify timeouts, visibility rules, XML page source generation, and XPath behavior.

    Common use cases include:

    • Adjusting timeouts for element visibility (waitForSelectorTimeout) or UI idling (waitForIdleTimeout).
    • Controlling the depth and content of the XML page source (e.g., allowInvisibleElements, includeExtrasInPageSource, snapshotMaxDepth).
    • Configuring MJPEG screenshot broadcasting parameters.
    • Managing XPath interpreter versions (enforceXPath1).
    // Example of how settings are conceptually applied via the Appium Settings API
    // (Note: Actual implementation depends on your Appium client language)
    driver.setSetting("waitForSelectorTimeout", 5000);
  3. How appium:uiautomator2.contextUpdate works

    master

    The appium:uiautomator2.contextUpdate event is emitted whenever a context change occurs, whether it is explicit or implicit. This event is also emitted during new session initialization.

    The event payload follows this structure:

    • name: The actual name of the new context (e.g., NATIVE_APP).
    • type: The type of the active context, which will be either NATIVE or WEB.
    appium:uiautomator2.contextUpdated = {
      method: "appium:uiautomator2.contextUpdated",
      params: {
        name: text,
        type: "NATIVE" / "WEB",
      },
    }
  4. How Android input events work

    master

    Android handles signals from input devices (touch screens, mice, keyboards) using InputEvent objects, specifically MotionEvent for touch and KeyEvent for keyboard interactions.

    To emulate a physical interaction (like a tap or swipe) via automation, you must generate a sequence of these event objects with specific properties (coordinates, timestamps, action types) that mimic the exact pattern a real device would produce. These events are then injected into the system using low-level methods like injectInputEvent via the IUiAutomationConnection interface.

  5. Understand Windows, Displays, and Hardware Displays in Android

    master

    When testing multi-window applications (Split-screen, PiP, Freeform, System overlays), it is important to distinguish between three layers of abstraction:

    1. Windows: Containers for UI elements belonging to an application. Each window has a windowId, packageName, bounds (rect), Z-order (layer), and state flags like isActive or isFocused.
    2. Displays (Logical Displays): Virtual screens that contain windows. The default display typically has displayId = 0. Additional displays can be external monitors or virtual displays.
    3. Hardware Displays (Physical Displays): The actual physical screen hardware. Multiple logical displays can map to a single physical display.

    Multi-Display Support by Android Version:

    • Android API 30+ (Android R): Full support. The driver can access windows across all displays via getWindowsOnAllDisplays(). You can target a specific display using the currentDisplayId setting.
    • Before Android API 30: Only the default display (displayId = 0) is accessible. currentDisplayId has no effect.
  6. Use UiSelector for element lookup in UiAutomator2

    master

    The UiAutomator2 driver supports element lookup using Google's native UiSelector and UiScrollable frameworks. Using these locators allows for flexible, high-performance referencing of complex element paths. When using UiSelector, you pass the selector string as the second argument to the find_element method with the :uiautomator strategy.

    Note: Avoid using index selectors where possible; prefer using .instance() for more reliable element targeting.

    find_element(:uiautomator, 'new UiSelector().className("android.widget.TextView").instance(0)')
  7. Compare Device MJPEG Server vs. mobile: startScreenStreaming

    master

    The UiAutomator2 driver provides two distinct ways to stream the screen. Choose based on your requirements:

    • Mechanism: Runs entirely on the Android device via the built-in UiAutomator2 server.
    • Setup: Requires setting appium:mjpegServerPort to forward the port to the host.
    • Pros: No host-side dependencies; simple TCP/HTTP stream.
    • Use Case: Live viewing in a browser, simple screen recording (e.g., via ffmpeg), or using the stream for screenshots.

    mobile: startScreenStreaming / stopScreenStreaming (GStreamer-based)

    • Mechanism: Starts a host-side MJPEG server using GStreamer to capture and broadcast the screen.
    • Setup: Requires the adb_screen_streaming feature and GStreamer (with gst-plugins-base, gst-plugins-good, and gst-plugins-bad) installed on the host machine.
    • Pros: Advanced encoding and network options via GStreamer pipelines.
    • Use Case: Complex host-side streaming requirements.
  8. How the Appium UiAutomator2 Driver architecture works

    master

    The Appium UiAutomator2 Driver operates within an automation host to bridge the gap between a test client and an Android device. The architecture follows this flow:

    1. Test Client: Test code uses an Appium Client Library (Java, Python, JS, etc.) to send W3C WebDriver commands over HTTP to the Appium Server.
    2. Automation Host: The Appium Server forwards session commands to the UiAutomator2 Driver. The driver manages the connection to the device using ADB (Android Debug Bridge) for port forwarding and Chromedriver Management (specifically for hybrid apps or webview contexts).
    3. Device Target: The driver communicates with the UiAutomator2 Server (an instrumentation HTTP API) on the device via ADB port forwarding. The UiAutomator2 Server then interacts with the UiAutomator Framework to perform UI interactions and access the accessibility tree of the Application Under Test (AUT). For webview contexts, Chromedriver is used to provide WebDriver capabilities directly within the webview.
    flowchart TD
      subgraph ClientSide["Test Client"]
        T["Test Code"]
        CL["Appium Client Library<br/>(Java / Python / JS / Ruby / C#)"]
      end
    
      subgraph ServerHost["Automation Host"]
        AS["Appium Server<br/>WebDriver HTTP API"]
        XD["UiAutomator2 Driver<br/>(appium-uiautomator2-driver)"]
        ADBM["ADB + Port Forwarding"]
        CDM["Chromedriver Management<br/>(hybrid / webview only)"]
      end
    
      subgraph DeviceTarget["Android Device / Emulator"]
        U2S["UiAutomator2 Server<br/>(instrumentation HTTP API)"]
        UIA["UiAutomator Framework"]
        CD["Chromedriver<br/>(in webview context)"]
        AUT["Application Under Test"]
      end
    
      T --> CL
      CL -->|"W3C WebDriver over HTTP"| AS
      AS -->|"Forwards session commands to driver"| XD
      XD -->|"Install, shell, forward ports"| ADBM
      XD -->|"Context switch to WEBVIEW_*"| CDM
      ADBM -->|"adb forward (e.g. host:8200 → device:6790)"| U2S
      CDM -->|"Chromedriver HTTP"| CD
      U2S -->|"UiAutomator APIs"| UIA
      UIA -->|"UI interactions + accessibility tree"| AUT
      CD -->|"WebDriver in webview"| AUT
  9. How Scheduled Actions work in UiAutomator2

    master

    Scheduled Actions allow you to run code on the server side asynchronously to handle transient UI elements (like popups or notifications) that might disappear before a standard HTTP-based WebDriver command can reach them.

    Key Concepts:

    • Asynchronous Execution: You describe an action in JSON, and the server executes it on the main UI thread independently of your test script's execution flow.
    • Action Types: Currently supports gesture (emulating user input), source (taking XML page source), and screenshot (taking PNG screenshots).
    • Lifecycle: Actions are scheduled by the client, run on the server, and can be inspected via history or stopped using unscheduleAction. All scheduled actions are automatically reset when a new session is created.
    • Availability: This feature is available in the UiAutomator2 driver since version 2.26.0.
    # Example of the mental model: 
    # 1. Schedule an action to run in the background
    driver.execute_script('mobile: scheduleAction', { ... })
    
    # 2. Perform other test steps that might trigger the UI event
    do_other_test_steps()
    
    # 3. Stop the action and retrieve the history to assert what happened
    history = driver.execute_script('mobile: unscheduleAction', { 'name': 'myAction' })
  10. Choose the correct locator strategy for multi-window apps

    master

    When testing multi-window applications, your choice of locator strategy is critical:

    • UiObject2-Based Locators (Recommended): Use id (resource ID), accessibility id (content description), className, or xpath. These support multi-window scenarios and are compatible with settings like enableMultiWindows and currentDisplayId.
    • Legacy UiObject-Based Selectors (Avoid): The -android uiautomator strategy uses the legacy UiSelector API. It does not support multi-window lookups and only searches within the active window. It cannot access elements in other windows even if enableMultiWindows is enabled.
  11. Configure XPath behavior in UiAutomator2

    master

    UiAutomator2 uses XPath2 by default (via Psychopath). If you encounter issues with sophisticated locators, you can force the driver to use the standard Android XPath1 implementation by setting enforceXPath1 to true.

    Additionally, you can control how context-based searches behave using limitXPathContextScope. By default (true), searches are limited to the parent element. Setting this to false allows the search to access the entire page source, but you must use the . notation (e.g., .//element) to ensure you are still searching within the intended descendant scope.

    // To fix issues with complex XPath2 locators:
    driver.setSetting("enforceXPath1", true);
    
    // To allow context-based searches to see the whole tree:
    driver.setSetting("limitXPathContextScope", false);
    // Note: When limitXPathContextScope is false, use dot notation for descendants:
    // driver.find_element(:xpath, ".//element")