Stephan's Stuff

Adventures in Android Development

Automate Screenshots

Generate your app screenshots automatically.


When you support multiple languages with your app you most likely want to make dedicated screenshots for your Google Play Store entry for every language. Since all developers are lazy and this is an annoying task, this should be automated.

In my current project, at my work, we do this by using an own created script which runs some adb commands and monkeyrunner1 to navigate between the screens. Though this is very flaky and error prone, since we reboot the device when the script changes the language of the phone. This only works with rooted devices though and sometimes the device needs longer to reboot.
With monkeyrunner you can take screenshots and navigate through an app with simulating touches on the screen. The simulated touches are not that reliable sometimes and often we had to post process the screenshots.
So the overall experience is not that satisfying, but still better than doing it by hand.
To get a rough number, we support 7 language on three different devices(phone, 7" and 10" tablets) with each 7 screens, so we have 147 images in total. You definitely don’t want to do this by hand.

Alternative way

I recently discovered fastlane2 and I think it’s awesome. It provides a toolchain which automates everything from the build process up to the deployment in the app store. Though it is mainly for iOS, but more tools for Android are evolving there.
So is screengrab3 a tool which automates your screenshot taking process. Screengrab is similar to our approach, but instead of monkeyrunner it uses Espresso4 for the navigation inside the app and the taking of the screenshots. This is a nice approach since monkeyrunner has to be written in python and even though it’s not that complex you still have to invest time to learn the language.

To setup screengrab you can easily install it with sudo gem install screengrab and adding androidTestCompile 'tools.fastlane:screengrab:[version]' to your build.gradle file. You also have to create a debug manifest file with the following permissions: DISABLE_KEYGUARD, WAKE_LOCK, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, CHANGE_CONFIGURATION(if you don’t already have them in your main manifest). One advantage of screengrab is that it provides a testrule for switching the locale and therefore the device/emulator doesn’t have to restart for this.

If you set everything up as described you are ready to write your code for taking the screenshots. I did this for my app Stopmotion and here is a simplified version of my class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@RunWith(JUnit4.class)
public class Screenshots {

    @ClassRule
    public static final LocaleTestRule localeTestRule = new LocaleTestRule();

    @Rule
    public ActivityTestRule<MainActivity> activityRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void testTakeScreenshot() {
        Screengrab.screenshot("main_screen");

        onView(withId(R.id.recyclerViewImageList))
                .perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));

        SystemClock.sleep(1000);
        onView(withId(R.id.expand_button)).perform(click());
        SystemClock.sleep(1000);
        Screengrab.screenshot("view_image");

        ...
    }
}

As you can see you just call Screengrab.screenshot("screenshot_name"); and screengrab will take a screenshot. This is easy, but has one disadvantage, it uses Window.getDecorView() of your activity to take a screenshot. The problem hereby is that getDevorView() returns a view “containing the standard window frame/decorations and the client’s content inside of that”. Therefore no content of the statusbar and navigation bar. As you can see on the following image: To execute screengrab you just have to compile your app and your tests and then run screengrab in your app’s project folder. Screengrap will guide you through the process, however you can define a Screengrabfile file inside your project with all necessary configurations. You can create a template file by simply running screengrab init. Inside this file you can define the languages, your apk path, your package and so on.

If you are using a newer version of adb screengrab will likely finish with an error after the second time you run it. The reason for this is that it wants to display the taken screenshots, but the path is wrong. (I’m pretty sure this will be solved in the near future since the developers are aware of it, if you want further information you can have a look at this PR, or this adb bugreport) Nevertheless if everything worked out you can find your screenshots in fastlane/metadata/android/[locale]/images/[deviceType]/.

In general screengrab is pretty handy if you want to easily automate your screenshots. Even though it has some drawbacks like the empty statusbar and the mentioned issue with newer adb versions. I personally would prefer it over the monkeyrunner/adb solution since it is easier to use and open source. And I’m pretty sure it will improve in the near future and more features will come.

Also it integrates with the fastlane toolchain which is also evolving for Android. Next step in this chain would be setting up supply which pushes your apk, as well as your screenshots and metadata to the Android Play Store.