Skip to content

Support full screen screenshot and favour them in a SystemUiTestRule - #163

Open
sergio-sastre wants to merge 1 commit into
masterfrom
feature/#137_take_full_screenshots
Open

Support full screen screenshot and favour them in a SystemUiTestRule#163
sergio-sastre wants to merge 1 commit into
masterfrom
feature/#137_take_full_screenshots

Conversation

@sergio-sastre

@sergio-sastre sergio-sastre commented Jul 29, 2026

Copy link
Copy Markdown
Owner

The SystemUiTestRule helps optimize for full screenshot tests with stable and reproducible statusbar and navigation bar

Summary by CodeRabbit

  • New Features
    • Added a testing utility to configure status bar time and navigation mode consistently.
    • Added full-screen screenshot capture, including status and navigation bars, after the interface becomes idle.

The SystemUiTestRule helps optimize for full screenshot tests with stable and reproducible statusbar and navigation bar
@sergio-sastre sergio-sastre linked an issue Jul 29, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds SystemUiTestRule to compose status-bar and navigation-mode test rules, plus a utility for capturing full-screen screenshots after the UI becomes idle.

Changes

System UI test capture

Layer / File(s) Summary
Full-screen bitmap capture
utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt
Adds drawFullScreenToBitmap() to wait for UI idleness and return a full-screen Bitmap from UiDevice.
System UI rule composition
utils/src/main/java/sergio/sastre/uitesting/utils/testrules/systemui/SystemUiTestRule.kt
Adds configurable status-bar and navigation-mode rule chaining with a convenience screenshot method.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Test
  participant SystemUiTestRule
  participant StatusBarTestRule
  participant NavigationModeTestRule
  participant UiDevice
  Test->>SystemUiTestRule: apply test rule
  SystemUiTestRule->>StatusBarTestRule: configure clock time
  SystemUiTestRule->>NavigationModeTestRule: configure navigation mode
  Test->>SystemUiTestRule: drawFullScreenToBitmap()
  SystemUiTestRule->>UiDevice: wait for idle and capture screenshot
  UiDevice-->>Test: return full-screen Bitmap
Loading

Poem

A bunny hops through bars so bright,
Sets clocks and gestures just right.
The screen grows still, the pixels bloom,
A bitmap captures every room.
Hare today, test green tomorrow!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: adding full-screen screenshot support and wiring it into SystemUiTestRule.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/#137_take_full_screenshots

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt (1)

14-15: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Synchronize System UI before capturing.

UiDevice.waitForIdle() waits for the current application, not necessarily for status/navigation-bar updates. The composed rules explicitly perform additional instrumentation idleness waits after changing System UI; mirror that synchronization here or verify a stronger stable-state condition before capturing. (developer.android.com)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt`
around lines 14 - 15, Update drawFullScreenToBitmap to synchronize
instrumentation/system UI after UiDevice.waitForIdle() and before
takeScreenshot(). Mirror the additional instrumentation idleness wait used by
the composed rules, or apply an equivalent stable-state check, while preserving
the existing screenshot behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt`:
- Around line 14-15: Update drawFullScreenToBitmap so it does not force-unwrap
the nullable result from UiDevice.takeScreenshot(). Return the nullable Bitmap
or explicitly handle null by throwing a descriptive IllegalStateException that
identifies the screenshot failure.

---

Nitpick comments:
In
`@utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt`:
- Around line 14-15: Update drawFullScreenToBitmap to synchronize
instrumentation/system UI after UiDevice.waitForIdle() and before
takeScreenshot(). Mirror the additional instrumentation idleness wait used by
the composed rules, or apply an equivalent stable-state check, while preserving
the existing screenshot behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ceac09af-25ab-4bc8-9cb6-0690b7cec124

📥 Commits

Reviewing files that changed from the base of the PR and between 704972b and 10870f6.

📒 Files selected for processing (2)
  • utils/src/main/java/sergio/sastre/uitesting/utils/testrules/systemui/SystemUiTestRule.kt
  • utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt

Comment on lines +14 to +15
fun drawFullScreenToBitmap(): Bitmap =
UiDevice.getInstance(getInstrumentation()).apply { waitForIdle() }.takeScreenshot()!! No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

curl -fsSL 'https://developer.android.com/reference/kotlin/androidx/test/uiautomator/UiDevice' \
  | grep -A8 -B2 'takeScreenshot(): Bitmap?'

Repository: sergio-sastre/AndroidUiTestingUtils

Length of output: 173


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== file exists =="
git ls-files | grep -F 'utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt' || true

echo "== file contents =="
cat -n 'utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt'

echo "== related usages =="
rg -n "drawFullScreenToBitmap|takeScreenshot\\(" .

echo "== dependency refs for uiAutomator =="
rg -n "androidx.test.uiautomator|uiautomator|UiDevice" . --glob '!build/**' --glob '!*.png' --glob '!*.jpg' | head -100

echo "== gradle deps around instrumentation =="
git ls-files | grep -E '(^|/)(build\.gradle|build\.gradle\.kts|gradle\.properties)$' | while read -r f; do
  echo "-- $f"
  sed -n '1,220p' "$f" | grep -n -i "androidx.test\|uiautomator\|instrumentation\|compileSdk\|minSdk" || true
done

Repository: sergio-sastre/AndroidUiTestingUtils

Length of output: 5283


🌐 Web query:

UiDevice takeScreenshot return type androidx.test.uiautomator

💡 Result:

In the androidx.test.uiautomator library, the UiDevice.takeScreenshot methods that save a screenshot to a file return a boolean value [1][2][3]. These methods return true if the screenshot was created and saved successfully, and false otherwise [4][5][3]. The available signatures for these methods are: - boolean takeScreenshot(File storePath) [2][6] - boolean takeScreenshot(File storePath, float scale, int quality) [2][6] Note that while there are other methods within the androidx.test.uiautomator package or extension libraries that return a Bitmap (such as those associated with UiObject2 or accessibility objects), the specific UiDevice.takeScreenshot methods designed to write to a File path return a boolean [2][6][7].

Citations:


🌐 Web query:

"UiDevice.takeScreenshot()" "Bitmap?" "androidx.test.uiautomator"

💡 Result:

The UiDevice.takeScreenshot() method in androidx.test.uiautomator does not return a Bitmap object; it returns a boolean indicating whether the screenshot was successfully saved to a specified File [1][2]. The standard UiDevice methods for taking screenshots require a file path to store the output [1][3]: * boolean takeScreenshot(File storePath): Saves a PNG to the specified file using default settings (1.0f scale, 90% quality) [1][2]. * boolean takeScreenshot(File storePath, float scale, int quality): Saves a PNG with customizable scale and quality [1][2]. If your goal is to obtain a Bitmap object directly for in-memory processing or visual assertions, the modern UI Automator framework provides alternative approaches [4]. When using the uiAutomator { ... } test block, you can capture bitmaps from specific UI components or windows [4]: val fullScreenBitmap: Bitmap = activeWindow.takeScreenshot val elementBitmap: Bitmap = onElement {... }.takeScreenshot Alternatively, for capturing the entire screen as a Bitmap outside of this specific DSL, you can use androidx.test.core.app.DeviceCapture.takeScreenshot(), which is designed to return a Bitmap [5]. Unlike the legacy UiDevice.takeScreenshot() method, DeviceCapture includes logic to ensure a stable screenshot by forcing the application's root window views to redraw [5]. Top results: [1][4][5]

Citations:


🌐 Web query:

androidx.test.core.app.DeviceCapture takeScreenshot return type

💡 Result:

The androidx.test.core.app.DeviceCapture.takeScreenshot() method returns a android.graphics.Bitmap object [1][2][3]. This method captures an image of the device's screen [2]. It is intended for debugging purposes where a full-screen image is required [2]. Note that the method throws an IllegalStateException if called on the main thread, as it relies on UiAutomation [2][4], and may throw a RuntimeException if the screenshot operation fails [2][4].

Citations:


🌐 Web query:

"UiDevice.java" "takeScreenshot" "Bitmap" "androidx.test.uiautomator"

💡 Result:

In the androidx.test.uiautomator library, the UiDevice class does not provide a public method that returns a Bitmap directly [1][2]. Instead, its screenshot capabilities are designed to capture the screen and save it directly to a file [1][3]. The available methods in UiDevice for taking screenshots are: 1. boolean takeScreenshot(File storePath): Takes a screenshot of the default display and saves it as a PNG file at the specified path, using a default scale of 1.0f and 90% quality [1][3][2]. 2. boolean takeScreenshot(File storePath, float scale, int quality): Takes a screenshot of the default display and saves it as a PNG file, allowing you to specify the scale and compression quality [1][3][2]. If you require a Bitmap object, you may need to capture the screen using alternative Android instrumentation methods (such as UiAutomation.takeScreenshot) or utilize the newer UI Automator API (if using the latest library versions), which provides more flexible screenshot and assertion capabilities through its own domain-specific language (DSL) [4][2]. Note that recent updates to the UI Automator framework have introduced a new, more expressive API that allows for capturing screenshots of specific UI elements or windows as Bitmaps [4]. Top results for reference: [1] https://developer.android.com/reference/androidx/test/uiautomator/UiDevice [3] https://developer.android.google.cn/reference/androidx/test/uiautomator/UiDevice [4] https://developer.android.com/training/testing/other-components/ui-automator [2] https://android.googlesource.com/platform/frameworks/support/+/efd96b5e24d301da39fd1e47b1031ac4df5608ed/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiDevice.java

Citations:


🌐 Web query:

"UiDevice.java" "boolean takeScreenshot" "UiAutomation" "Bitmap"

💡 Result:

In the Android testing ecosystem, UiDevice and UiAutomation provide distinct methods for capturing screenshots, differing primarily in their return types and intended use cases. UiDevice (part of androidx.test.uiautomator) provides methods that store a screenshot directly to a file on the device's storage [1][2]. These methods return a boolean to indicate whether the operation was successful [3][1]. - Method: boolean takeScreenshot(File storePath) [1][4] - Method: boolean takeScreenshot(File storePath, float scale, int quality) [1][4] These methods are designed for high-level UI testing, where saving the screenshot to a specific path is the primary objective [3][5]. UiAutomation (part of android.app) provides a lower-level, more direct way to obtain a screenshot as a Bitmap object [6][7]. - Method: Bitmap takeScreenshot [6][7] (Available since API level 18) - Method: Bitmap takeScreenshot(Window window) [6][7] (Available since API level 34) The UiAutomation methods return a Bitmap directly, which allows for programmatic inspection, comparison, or manipulation of the pixel data within the test code [8][9]. If the capture fails, these methods return null [6][8][7]. In summary, use UiDevice when you need to save a screenshot file to disk for test reporting, and use UiAutomation when you need to work with the Bitmap data in memory [1][6][8].

Citations:


🌐 Web query:

"UiDevice.java" "UiDeviceBitmapProvider" "takeScreenshot()" null

💡 Result:

When UiDevice.takeScreenshot returns null or fails, it typically indicates that the underlying UiAutomation.takeScreenshot call failed to capture a valid bitmap [1][2]. This commonly occurs due to environment-specific limitations rather than a bug in the code itself [3][4]. The takeScreenshot method in UiDevice relies on the system-level UiAutomation bridge [1]. If the system is unable to return a bitmap—often because the window has not been laid out, lacks a surface control, or has encountered an internal error in SurfaceFlinger—the method returns null [2]. Common causes for this issue include: 1. Security Restrictions: If the target application has set the FLAG_SECURE window flag, the system intentionally prevents screenshots, which will cause the capture to return null [3]. 2. Emulator/AVD Configurations: Using hardware acceleration (GPU) or snapshot features in certain AVD configurations has historically caused issues with UI Automator screenshots [3]. Disabling these features or testing on a physical device is a common workaround [3]. 3. Permissions and File Access: Ensure the application has the necessary storage permissions and that the provided file path is valid and writable [5]. 4. ADB and Tool State: Sometimes the ADB process or the UI Automator viewer itself can enter a state where it fails to communicate correctly with the device. Restarting the ADB server or reconnecting the device can resolve transient issues [4]. To debug, verify if the issue persists across different applications; if it is isolated to one app, it is likely caused by the FLAG_SECURE flag or similar security policies [3][4]. If it happens globally, investigate the emulator settings or physical device environment [3][5].

Citations:


🌐 Web query:

site:github.com/android/uiautomator UiDevice.java public Bitmap takeScreenshot

💡 Result:

The Bitmap version is:

public @nullable Bitmap takeScreenshot()

in androidx.test.uiautomator.UiDevice (added in 2.4.0). The source is in the AndroidX UiDevice.java file, and the API docs confirm it returns the screenshot bitmap or null on failure. (android.googlesource.com)

If you meant the older platform API, android.app.UiAutomation also has public Bitmap takeScreenshot(). (developer.android.com)

Citations:


Avoid force-unwrapping the screenshot result.

UiDevice.takeScreenshot() returns a nullable Bitmap; replacing the opaque NullPointerException with a nullable result or a descriptive IllegalStateException makes screenshot failures easier to diagnose.

Proposed fix
 fun drawFullScreenToBitmap(): Bitmap =
-    UiDevice.getInstance(getInstrumentation()).apply { waitForIdle() }.takeScreenshot()!!
+    UiDevice.getInstance(getInstrumentation())
+        .apply { waitForIdle() }
+        .takeScreenshot()
+        ?: error("Unable to capture a full-screen screenshot")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fun drawFullScreenToBitmap(): Bitmap =
UiDevice.getInstance(getInstrumentation()).apply { waitForIdle() }.takeScreenshot()!!
fun drawFullScreenToBitmap(): Bitmap =
UiDevice.getInstance(getInstrumentation())
.apply { waitForIdle() }
.takeScreenshot()
?: error("Unable to capture a full-screen screenshot")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@utils/src/main/java/sergio/sastre/uitesting/utils/utils/DrawFullScreenToBitmap.kt`
around lines 14 - 15, Update drawFullScreenToBitmap so it does not force-unwrap
the nullable result from UiDevice.takeScreenshot(). Return the nullable Bitmap
or explicitly handle null by throwing a descriptive IllegalStateException that
identifies the screenshot failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support to take Full-Screen screenshots

1 participant