screenshots
screenshots copied to clipboard
Use actual Navbar on Android Devices
It would be awesome if this library could include the actual navigation bar from the device. Screenshots from android devices could really benefit from this because the look of the navbar may depend on the app and the device. iOS devices are not affected by this since they don't have a navigation bar.
I just tried to add a Pixel 4 XL frame and got this result:
| Generated screenshot | How it could look like |
|---|---|
![]() |
![]() |
Screenshots are currently taken using flutter driver. The screenshot method returns a screenshot of the app without the navigation bar. The navigation bar is currently a separate png file that gets appended below the screenshot. This results in a few limitations:
- You have to create a new navigation bar for every new device.
- Some apps customize the color & brightness of the navigation bar. The navbar color on the screenshots will be black (or the color of navbar.png) regardless of the actual color. (More Details).
How this could be solved It is possible to take a full screenshot (including the navigation bar) using adb:
adb exec-out screencap -p > screen.png
Using this command would simplify processing the screenshot in this library and we wouldn't have to deal with the navigation bar anymore. The downside of that solution would be that we'll lose the clean status bar. I haven't found a solution for this issue except taking two screenshots and extracting the navbar.png from the adb screenshot.
Any thoughts on this?
I guess demo mode would help customizing the status bar. It can be enabled in developer options or on command line:
adb shell settings put global sysui_demo_allowed 1
adb shell am broadcast -a com.android.systemui.demo -e command enter
For example: Set the clock to 12:31
adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1231
Looks great! I just modified the screenshot() function in capture_screen.dart and got very promising results. This is the code I used to create screenshots using adb:
final testDir = '${config.stagingDir}/$kTestScreenshotsDir';
final file = await File('$testDir/$name.$kImageExtension').create(recursive: true);
if(adbScreenshots){
await Process.run('adb', ['shell', 'settings', 'put', 'global', 'sysui_demo_allowed', '1']);
await Process.run('adb', ['shell', 'am', 'broadcast', '-a', 'com.android.systemui.demo', '-e', 'command', 'enter']);
await Process.run('adb', ['shell', 'am', 'broadcast', '-a', 'com.android.systemui.demo', '-e', 'command', 'clock', '-e', 'hhmm', '1600']);
await Process.run('adb', ['shell', 'am', 'broadcast', '-a', 'com.android.systemui.demo', '-e', 'command', 'notifications', '-e', 'visible', 'false']);
final screenshotResult = await Process.run('adb', ['exec-out', 'screencap', '-p'], stdoutEncoding: null);
await file.writeAsBytes(screenshotResult.stdout);
await Process.run('adb', ['shell', 'am', 'broadcast', '-a', 'com.android.systemui.demo', '-e', 'command', 'exit']);
}else{
final pixels = await driver.screenshot();
await file.writeAsBytes(pixels);
}
Maybe we can use adb to take screenshots of devices running android 6 (that version introduced demo mode) or greater.
However we would need some way to pass the adb device id to the test driver which is running in a separate process. This is necessary to make sure that we take screenshots of the correct device when more than one device is connected.
Unfortunately I don't know any elegant solution that would solve this issue. We can't just pass arguments to the flutter process because this would require all users to modify at least their test_driver/main.dart. Does anyone have an idea how this could be solved?
A screenshots runtime env file is created before the start of each test. The runtime env is readable by the test. It's possible to add the device id there.
The screenshot() function can be modified to use this env file.
The returned screenshot will have to be processed differently (skip overlaying a status bar and skip appending a nav bar). If it works, should probably be the default way to handle screenshots from android.

