maestro icon indicating copy to clipboard operation
maestro copied to clipboard

App needs to be launched in CI for Android without a GUI, Maestro struggles to relaunch the app in foreground.

Open ArnauBuild opened this issue 3 months ago • 21 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues and didn't find mine.

Steps to reproduce

Execute any flow with multiple launchApp, killApp

Actual results

Context We're running Maestro tests in a CI environment (headless Android setup, no GUI). The app under test needs to be launched (or relaunched) in the foreground during the test flow.

Problem Maestro appears to struggle with relaunching the app in the foreground after the first launch. Specifically: On the second launch, Maestro seems unable to bring the app to the foreground. As a result, it fails to find the expected UI element—even though it's visible on the screen. The test hangs for 15–20 seconds waiting for the element to appear, and eventually fails.

Expected behavior Maestro should be able to reliably relaunch and foreground the app. UI element queries should succeed if the element is on screen.

Expected results

It should keep executing the flow on the second time the app starts.

About app

It's an apk for Android

About environment

Java version: OpenJDK 17 MacBook Pro M1 Emulator uses arm64

Logs

Logs
<!-- Replace this line with your logs. *DO NOT* remove the backticks! -->

Maestro version

2.0.3

How did you install Maestro?

Homebrew

Anything else?

Adding delays or retries does not help.

Logcat shows the app is running, but it might be backgrounded or not properly focused.

ArnauBuild avatar Sep 29 '25 10:09 ArnauBuild

Did you want to share any details about how you're going about the launching of the app, the logs when it fails, how you're launching the emulator? Right now, this doesn't contain enough detail to actionable.

Fishbowler avatar Sep 29 '25 12:09 Fishbowler

FLOW:

----- Launch App and perform setup -----

- launchApp:
    clearState: true
- assertVisible: "Setup XXX"
- tapOn: "Setup XXX"
- assertVisible: "XXX YYYYYY."
- killApp:
    appId: ${app_id}

----- Install Current Version -----

- runScript:
    file: ../terminal.js
    env:
        exec: 'source scripts/params.env; ls build/$CURRENT_VERSION_GIT_PATH/androidBuild/'
        async: false
    label: "Show me the apk files in the current version"
- assertTrue:
    condition: "${output.terminal == 'app.apk'}"
    label: "Apk from current version is present"
- runScript:
    file: ../terminal.js
    env:
        exec: 'source scripts/params.env; adb install -r build/$CURRENT_VERSION_GIT_PATH/androidBuild/app.apk'
        async: false
    label: "Install current version of XXX sample"
# ----- Launch App without clear state and perform setup -----
- launchApp:
    clearState: false
- assertVisible: "Setup XXX"                               **_FAILS HERE_**
- tapOn: "Setup XXX"
- assertVisible: "XXX YYYYYY."

LOGS:

13:15:16.407 [ INFO] MAESTRO.logSystemInfo: ---- System Info ----
13:15:16.408 [ INFO] MAESTRO.logSystemInfo: Maestro Version: 2.0.3
13:15:16.408 [ INFO] MAESTRO.logSystemInfo: CI: jenkins
13:15:16.408 [ INFO] MAESTRO.logSystemInfo: OS Name: Mac OS X
13:15:16.409 [ INFO] MAESTRO.logSystemInfo: OS Version: 14.5
13:15:16.409 [ INFO] MAESTRO.logSystemInfo: Architecture: aarch64
13:15:16.409 [ INFO] MAESTRO.logSystemInfo: Java Version: 17
13:15:16.456 [ INFO] MAESTRO.logSystemInfo: Xcode Version: 16.2
13:15:16.471 [ INFO] MAESTRO.logSystemInfo: Flutter Version: Undefined
13:15:16.487 [ INFO] MAESTRO.logSystemInfo: Flutter Channel: Undefined
13:15:16.487 [ INFO] MAESTRO.logSystemInfo: ---------------------
13:15:21.062 [ INFO] maestro.cli.command.TestCommand.runShardSuite: [shard 1] Selected device emulator-5554 using port 7001
13:15:28.782 [ INFO] maestro.orchestra.Orchestra.initAI: [Orchestra] Initializing AI
13:15:28.783 [ INFO] maestro.Maestro.invoke: Getting device info
13:15:29.105 [ INFO] maestro.Maestro.invoke: Got device info: DeviceInfo(platform=ANDROID, widthPixels=1440, heightPixels=2960, widthGrid=1440, heightGrid=2960)
13:15:29.285 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Define variables RUNNING
13:15:29.289 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Define variables COMPLETED
13:15:29.289 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Apply configuration RUNNING
13:15:29.291 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Apply configuration COMPLETED
13:15:29.291 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Run flow when "System UI isn't responding" is visible RUNNING
13:15:35.917 [ INFO] maestro.orchestra.Orchestra.executeCommands: [Command execution] CommandSkipped: null
13:15:35.917 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Run flow when "System UI isn't responding" is visible SKIPPED
13:15:35.917 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Show me the apk files in the previous version RUNNING
13:15:36.109 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Show me the apk files in the previous version COMPLETED
13:15:36.109 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Apk from previous version is present RUNNING
13:15:36.111 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Apk from previous version is present COMPLETED
13:15:36.111 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Install previous version of XXX RUNNING
13:15:36.986 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Install previous version of XXX COMPLETED
13:15:39.001 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Launch app "${app_id}" with clear state RUNNING
13:15:39.002 [ INFO] maestro.Maestro.clearAppState: Clearing app state ZZZ
13:15:39.404 [ INFO] maestro.Maestro.launchApp: Launching app ZZZ
13:15:39.490 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Launch app "${app_id}" with clear state COMPLETED
13:15:43.262 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Assert that "Setup XXX" is visible RUNNING
13:15:43.410 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Assert that "Setup XXX" is visible COMPLETED
13:15:43.411 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Tap on "Setup XXX" RUNNING
13:15:43.529 [ INFO] maestro.Maestro.tap-BUbHBYE: Tapping on element:  UiElement(treeNode=TreeNode(attributes={text=Setup XXX, accessibilityText=, hintText=, ignoreBoundsFiltering=false, resource-id=ZZZ:id/startButton, clickable=true, bounds=[283,553][1158,721], enabled=true, focused=true, checked=false, scrollable=false, selected=false, class=android.widget.Button}, children=[], clickable=true, enabled=true, focused=true, checked=false, selected=false), bounds=Bounds(x=283, y=553, width=875, height=168))
13:15:44.337 [ INFO] maestro.Maestro.tap-BUbHBYE: Refreshed element
13:15:44.338 [ INFO] maestro.Maestro.hierarchyBasedTap-hbl3e4M: Tapping at (720, 637) using hierarchy based logic for wait
13:15:44.338 [TRACE] maestro.utils.ScreenshotUtils.takeScreenshot: Taking screenshot to byte array
13:15:44.338 [TRACE] maestro.utils.ScreenshotUtils.takeScreenshot: Taking screenshot to output sink
13:15:46.339 [ INFO] maestro.Maestro.hierarchyBasedTap-hbl3e4M: Something have changed in the UI judging by view hierarchy. Proceed.
13:15:46.340 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Tap on "Setup XXX" COMPLETED
13:15:46.340 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Assert that "XXX registration was successful." is visible RUNNING
13:15:51.361 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Assert that "XXX registration was successful." is visible COMPLETED
13:15:51.361 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Kill ${app_id} RUNNING
13:15:51.362 [ INFO] maestro.Maestro.killApp: Killing app ZZZ
13:15:51.390 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Kill ${app_id} COMPLETED
13:15:51.390 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Show me the apk files in the current version RUNNING
13:15:51.403 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Show me the apk files in the current version COMPLETED
13:15:51.403 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Apk from current version is present RUNNING
13:15:51.404 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Apk from current version is present COMPLETED
13:15:51.404 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Install current version of XXX sample RUNNING
13:15:54.198 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Install current version of XXX sample COMPLETED
13:15:56.206 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Launch app "${app_id}" RUNNING
13:15:56.424 [ INFO] maestro.Maestro.launchApp: Launching app ZZZ
13:15:56.487 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Launch app "${app_id}" COMPLETED
13:15:57.298 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Assert that "Setup XXX" is visible RUNNING
13:16:14.462 [ERROR] maestro.orchestra.Orchestra.executeCommands: [Command execution] CommandFailed: Assertion is false: "Setup XXX" is visible
13:16:14.462 [ INFO] maestro.cli.runner.TestSuiteInteractor.invoke: Assert that "Setup XXX" is visible FAILED

PROBLEM: It should return that that text (Setup XXX) is visible, because it is, but as the app isn't on the foreground on the second execution of the app, and so it doesn't detect it. This only happens on Android, in iOS works as expected.

ArnauBuild avatar Sep 30 '25 10:09 ArnauBuild

This APK listing stuff works by default in Maestro, without modification?

Fishbowler avatar Sep 30 '25 10:09 Fishbowler

but as the app isn't on the foreground on the second execution of the app, and so it doesn't detect it

How do you know the app isn't in the foreground?

You said in your initial report:

On the second launch, Maestro seems unable to bring the app to the foreground. As a result, it fails to find the expected UI element—even though it's visible on the screen.

If it's on the screen, isn't that the foreground? Or do we have some terminology confusion?

Fishbowler avatar Sep 30 '25 11:09 Fishbowler

I saw this logs on the logcat, while executing locally, but without a GUI (when opening the app for the second time): 16:39:03.414 2386 2409 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 16:39:03.414 2386 2409 W UiDevice: Active window root not found.

I tried to add delays, to press Home or Enter button, or to launch app with adb command directly, but nothing worked.

ArnauBuild avatar Sep 30 '25 12:09 ArnauBuild

I'm unsure that any of this is definitive.

Does it all work locally?

Fishbowler avatar Sep 30 '25 13:09 Fishbowler

No, locally works as expected. It's just when it's executed on a CI environment, in which there are emulators without GUI. With iOS works fine

ArnauBuild avatar Oct 09 '25 08:10 ArnauBuild

Is it possible to launch an emulator headless on a desktop, in order to validate whether this is emulator vs Maestro vs CI environment vs a combination?

Fishbowler avatar Oct 09 '25 21:10 Fishbowler

I tried it several times to run it on a headless emulator locally. It always worked expect one time, in which it didn't. In a CI environment, it has never worked.

ArnauBuild avatar Oct 10 '25 07:10 ArnauBuild

I reproduced this issue locally, and I got the logcat. Analizing it, what appears to be happening is that:

  • After the second launch app, the app launches successfully, however, in my flow, I have this adb commands: - runScript: file: ../terminal.js env: exec: 'source scripts/params.env; adb install -r build/$CURRENT_VERSION_GIT_PATH/androidBuild/app.apk' async: false label: "Install current version of XXX sample"

  • And it looks like when doing the adb commands, maestro loses the ability of seeing the UI.

Here is a part of the logcat: 10-14 14:53:49.231 561 582 I ActivityTaskManager: Displayed com.X.X.X/X.X.X.X.MainActivity for user 0: +1s983ms 10-14 14:53:49.266 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.266 2352 2522 D Maestro : Requesting view hierarchy 10-14 14:53:49.266 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.266 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.267 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.267 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.267 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.267 2352 2522 W UiDevice: Active window root not found. 10-14 14:53:49.267 2352 2522 D Maestro : View hierarchy received in 1 ms 10-14 14:53:49.280 2604 2609 I X.X.X: Compiler allocated 5250KB to compile void android.view.ViewRootImpl.performTraversals() 10-14 14:53:49.377 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.377 2352 2522 D Maestro : Requesting view hierarchy 10-14 14:53:49.378 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.378 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.378 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.378 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.378 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.378 2352 2522 W UiDevice: Active window root not found. 10-14 14:53:49.378 2352 2522 D Maestro : View hierarchy received in 1 ms 10-14 14:53:49.412 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.412 2352 2522 D Maestro : Requesting view hierarchy 10-14 14:53:49.412 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.412 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.412 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.412 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.412 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.412 2352 2522 W UiDevice: Active window root not found. 10-14 14:53:49.412 2352 2522 D Maestro : View hierarchy received in 0 ms 10-14 14:53:49.457 561 681 I ImeTracker: com.X.X.X:937b2bf9: onRequestHide at ORIGIN_SERVER reason HIDE_UNSPECIFIED_WINDOW fromUser false 10-14 14:53:49.457 561 681 I ImeTracker: com.X.X.X:937b2bf9: onCancelled at PHASE_SERVER_SHOULD_HIDE 10-14 14:53:49.500 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.500 2352 2522 D Maestro : Requesting view hierarchy 10-14 14:53:49.501 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.501 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.501 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.501 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.501 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.501 2352 2522 W UiDevice: Active window root not found. 10-14 14:53:49.501 2352 2522 D Maestro : View hierarchy received in 1 ms 10-14 14:53:49.544 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.545 2352 2522 D Maestro : Requesting view hierarchy 10-14 14:53:49.545 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.545 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.545 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.545 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.545 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.545 2352 2522 W UiDevice: Active window root not found. 10-14 14:53:49.545 2352 2522 D Maestro : View hierarchy received in 0 ms 10-14 14:53:49.622 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.623 2352 2522 D Maestro : Requesting view hierarchy 10-14 14:53:49.623 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.623 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.623 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.623 2352 2522 W QueryController: Could not detect idle state. 10-14 14:53:49.623 2352 2522 W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. 10-14 14:53:49.623 2352 2522 W UiDevice: Active window root not found.

ArnauBuild avatar Oct 14 '25 13:10 ArnauBuild

It not only happens with the adb install, I have other adb commands that I need to make, such as adb pull/adb push/... that also fail

ArnauBuild avatar Oct 14 '25 13:10 ArnauBuild

Given that Maestro runs in the context of the device, rather than any given app, I would expect that installing or replacing an app (even the one specified by appId) would have any effect.

A quick check of the source suggests that an interaction with an app that ends with waitForAppToSettle (like tapOn) does use the appId in that specific context to ensure that it's the app's window that becomes stable (so not taking account of clock changes, for example).

I haven't found any other instances. Could your app install scripting be happening too soon after an interaction with the app?

(Side note: I'm quietly pleased that Maestro isn't broken for everyone using CI, and that this is a confluence of advanced interactions)

Fishbowler avatar Oct 14 '25 13:10 Fishbowler

I have tried to place this code, before and after the adb calls:

  • runScript: file: ../terminal.js env: exec: 'sleep 2' async: false label: "Wait for 2 seconds"

In a CI environment, it has never worked.

I have also tried to do the adb command at first, before doing the first launchApp, and it also failed, once I need to do an assertVisible or tapOn. It's like the adb command makes that maestro loses the UI.

It's just on this case and for Android, for iOS on CI it has always worked, and I tried also easier flows without adb commands and worked.

ArnauBuild avatar Oct 14 '25 14:10 ArnauBuild

As a summary of what's this issue about: Summary After executing adb install commands within a Maestro test flow, the accessibility service loses its ability to inspect the UI hierarchy, causing all subsequent UI interactions to fail with "Active window root not found" warnings.

Issue Description When running a single test flow that includes multiple adb install commands executed via runScript, Maestro's accessibility service becomes unable to retrieve the view hierarchy after the installation completes. The app launches successfully, but Maestro cannot interact with it.

Steps to Reproduce Execute adb install -r -g app.apk via runScript in a Maestro flow Wait 2+ seconds for the installation to complete Attempt to launch the app with launchApp Try to interact with UI elements using assertVisible or tapOn

Expected Behavior Maestro should be able to inspect and interact with the UI after ADB install commands, just as it does when tests are split into separate YAML files.

Actual Behavior Maestro requests view hierarchy but receives empty response Logs show: W UiDevice: Active window root not found. Logs show: D Maestro : View hierarchy received in 0 ms Logs show: W UiDevice: Cannot verify accessibility service flags. Multi-window support (searching non-active windows) may be disabled. All UI assertions fail with timeout (even with 20+ second default timeout) The app itself is running correctly and displays UI elements

Anything else it's required, I'm happy to send/test

ArnauBuild avatar Oct 14 '25 15:10 ArnauBuild

Maestro uses dadb under the hood, rather than using the adb binaries. I wonder if there's some conflict there? If so, it might not be a solvable one.

A quick thought - do adb commands work immediately before the test? If nothing occurs before the tests, could adb be restarting the connection or similar?

Fishbowler avatar Oct 16 '25 10:10 Fishbowler

ADB commands are definitely working — I can see them completing successfully in the logs. The next command (launchApp) also runs fine, but after that Maestro is no longer able to obtain the UI hierarchy.

I tried splitting the test into multiple smaller ones, where each test includes its own launchApp followed by the ADB command, and that approach works fine.

Could it be that the Maestro accessibility permissions were lost or revoked?

ArnauBuild avatar Oct 16 '25 14:10 ArnauBuild

My point was more whether ADB was already running and ready before the test started

Fishbowler avatar Oct 16 '25 18:10 Fishbowler

Yes, it was already running. I even tried to place an adb command just before executing the maestro test command, and still fails.

ArnauBuild avatar Oct 17 '25 09:10 ArnauBuild

Unsure if this is a Maestro problem to solve, or something in dadb, or something that's a little more "this is a constraint".

Fishbowler avatar Oct 18 '25 22:10 Fishbowler

Your test flow is definitely outside of the "normal" operation of Maestro - most folks won't be trying to run adb commands mid-flow. Because of that, you're unlikely to find a staff or community member who will be willing to pick this up and take it further on your behalf.

Fishbowler avatar Dec 01 '25 11:12 Fishbowler