Framing Android screenshots

Ricardo Belchior
Feb 27, 2020 · 6 min read

At Reach we wanted to improve our release process by automating the process of taking screenshots and uploading them to the Play Store.

Adding screenshots is an important step to showcase an app’s features and functionality. It can attract new users and highlight certain use cases of the app. It’s one of the most important elements of ASO (app store optimisation), which if done correctly, can help improve the app’s ranking on the Play Store.

However there can be a few challenges in creating and maintaining your screenshots for production apps over time. When you implement new features or even small changes in your design, it’s nice to keep your screenshots up to date. Depending on the way you prepare and design your screenshots, this can become very time consuming.

For example, if a designer needs to be involved to create the assets, then it means on every release you need to wait for the designer to prepare your screenshots and have them ready as soon as you release the app. Or if you have videos (which Google recommends), you might have to ask an external team to rebuild the videos over and over again.

This situation can get 40 times worse if you have 40 different apps on the PlayStore, which is our case — we have one base source code rebranded into many publications of Reach plc. The sad reality is that sometimes we’ve held off releasing an app update, or had the screenshots that didn’t show the latest features of the app. And it was always a burden for the designer who had the tedious task of preparing screenshots for 40 different apps.

1) Taking screenshots on Android

Taking screenshots on Android is technically an easy process and there are many alternatives out there, such as AndroidX Screenshot, Spoon and Screengrab.

A common practice is to prepare a set of Espresso tests, inject some dummy data in your app and use one of those APIs to take screenshots and store them in the sdcard. Having a good architecture will help, because you’ll need to change your data sources and prepare your app so that it behaves consistently every time. These are similar challenges to writing consistent tests using the Espresso framework. If you have a stable CI process for that, you’re in good shape. Here’s a snippet of our Espresso test for taking screenshots:

Snippet of our Espresso test for taking screenshots

Once this is done you’ll have a set of images of your app in different screens/devices/orientations. This by itself can be a valuable step in order to:

  • Reduce the work of manually taking screenshots
  • Provide consistent data for your screenshots
Example screenshots from an Espresso test

However, there isn’t a description or device frame or background image. These are usually not very exciting images to promote your app. In the next step I’ll describe how we automated our process into the next level.

2) Framing your screenshots

The goal here was to have a simple way of putting a device ‘around’ the screenshot and adding some text as a description. But as far as I know there aren’t many resources online describing how to do this.

It turns out our iOS colleagues (thanks to Stephen Brown) were already doing this with ease. This step is quite trivial on iOS using Fastlane and its frameit tool:

frameit allows you to put a gorgeous device frame around your iOS and macOS screenshots just by running one simple command. Use frameit to prepare perfect screenshots for the App Store, your website, QA or emails.

App Store… website… emails… but not Android :(

Luckily, Fastlane is open source and someone was already looking into it. In the Fastlane project on GitHub there are two opened PRs from milhauscz which are meant to provide support for Android frames:

Hopefully these will be merged soon, but until then, I was able to clone the branches and run them locally.

You can find instructions here on how to setup Fastlane for your project. I do recommend you use Bundler and a Gemfile to specify your Ruby dependencies. This is the recommended Ruby package manager and every time you run fastlane through the terminal, it is advised to use bundle exec fastlane <command>

Clone fastlane and frameit-frames:

cd ~/workspace
git clone git@github.com:fastlane/fastlane.git
cd fastlane
git remote add milhauscz git@github.com:milhauscz/fastlane.git
git checkout milhauscz/master
cd ~/workspace
git clone git@github.com:fastlane/frameit-frames.git
cd frameit-frames
git remote add milhauscz git@github.com:milhauscz/frameit-frames.git
git checkout milhauscz/gh-pages

Fix offsets.json

In order for the rest of the process to work I had to fix a typo in the offsets.json file of the frameit-frames repository:

  • Change Nexus 5x to Nexus 5X (capital X)

offsets.json is a configuration file with a list of device frames and their respective dimensions, so that Fastlane knows where to place the screenshot inside the frame

Run your local version of Fastlane

Change the version of Fastlane at version.rb in the Fastlane repository to something you can recognise, like 2.141.100.SNAPSHOT

Then in your Android project, in order to run Fastlane from your local folder, open the Gemfile and replace the line: gem fastlane with:

gemspec path: File.expand_path(".../workspace/fastlane")

To ensure the process worked out, in your project run in the terminal:

bundle update fastlane
bundle exec fastlane -v

You should see the SNAPSHOT version you specified earlier. Now we’re almost there.

Running frameit

The first thing to do is prepare a Framefile.json , according to the documentation. In this file you are able to customise a background colour, some text to add on the top/bottom of the screenshot, which font to use and so on. Just make sure to include this file in the screenshots folder, so that frameit can find it.

Finally, you can run the frameit action like this:

bundle exec fastlane frameit \
use_platform:android \
path:screenshots_output

Fastlane will look into the screenshots_output folder and attempt to put a frame on every image inside it.

Screenshots after running frameit

In case you want to use different devices frames, you want to make sure the image resolutions match the ones that Fastlane is expecting. It is also possible to force a specific device type. You can find all available parameters by running: bundle exec fastlane actions frameit

3) Uploading screenshots

The final step is to automate the process of uploading the screenshots into the PlayStore. If you’ve come this far, this is now a trivial step using Fastlane’s supply action:

supply(
package_name: com.reachplc.app,
skip_upload_screenshots: false,

skip_upload_apk: true,
skip_upload_aab: true,
skip_upload_metadata: true,
skip_upload_changelogs: true,
skip_upload_images: true)

Just make sure you’re putting the framed screenshots in the folder structure accepted by supply:

This Fastlane action also allows you to upload a number of other resources such as feature images, changelogs, etc. but I’m not focusing on that here.

In order to make this whole process smoother, we have a simple bash script running all three steps sequentially, for each publication, within our CI machine.

I hope you have enjoyed this blog post. I wish I’d had this information a few months ago, so even though this won’t be the right solution for everyone, it might help someone out there =)

Thanks to Richard Jordan for the logo and Stephen Brown for reviewing.

Let me know your thoughts in the comments area and feel free to follow me on Twitter https://twitter.com/belchii

Reach Product Development

The product development and engineering teams behind Reach…