Continuous Integration for Mobile Apps with Jenkins: Multi-Device Android Builds

Written by: Hannah Inman
4 min read

In a previous blog post in this series about continuous integration for mobile apps with Jenkins, I showed examples of how to run Android builds using remote agents, in the same way that you might run iOS builds (see this blog for more details on how to set that up). That's all very well and may be what you need to do in some circumstances, such as when you want to run tests using an actual, tethered device. However, when developing for Android that's probably not what you would want to do most of the time: you just want your changes to be built and tested automatically against the Android SDK's emulator, only doing actual physical device testing at key milestones. For these regular automatic build jobs, Jenkins as a service running on the CloudBees PaaS is the perfect tool since we can allocate build executors on-demand, without any software set-up or hardware required.

Another feature of Android development is the number of possible device configurations that a mobile app might need to support. This contrasts with the iOS world, where there are only a certain number of combinations you need to worry about: sure, you have different iOS versions and several devices (iPad, iPhone, iPod Touch) which could have different memory specs, for example, but with Android there are so many more combinations of underlying system image and device capability to worry about. Again, Jenkins is a perfect match for this challenge: with its multi-configuration "matrixed" build jobs, Jenkins can kick off any number of similar build/test cycles, all modeled on a single "template" but each running against a distinct set of device characteristics and emulator specs. You can see an example of a multi-configuration Android build online and here's the matrix of builds it defines:

As you can see, I've chosen three axes for the matrix build (screen density, locale and architecture) but for a real build system, I could and would add other axes and many more combinations. The beauty of being able to run all these in the cloud is that I don't have to worry about resources for these builds: Jenkins will automatically allocate executors from the pool of available resources on-demand. Here's how you would go about setting this up: first, create a new Jenkins job and choose the "Build multi-configuration project" option; then define the axes like this in the Configuration Matrix section:

These axes (density, locale and target-abi) map to the properties (${density}, ${locale}, ${target-abi}) used in the Android Emulator configuration, like so:

You'll find more information on the Jenkins Android Emulator Plug-in page, which also has a nice example of how you can remove elements from the Matrix of builds (for example, where a particular screen density is nonsensical for certain device configurations) using a "Combination Filter" in Jenkins. Another interesting use for Combination Filters is to have Jenkins automatically select a subset of build configurations from the matrix: during development, you might want only a "sample" subset of device configurations to be tested, as a sanity check, with the full matrix used for formal build milestones. An example of that would be a combination filter like this: index%2==0; this would select half the build configurations to run (Jenkins will choose the set to ensure that all the axes get as much coverage as possible, within the constraints you set).

When running Android builds (single or multi-configuration) using Jenkins in the cloud, the Android SDK will automatically be mounted: you specify the appropriate Android target in your build properties as in the example below. The Android project is updated from SCM (and the project workspace refreshed), then we run the android project update command to set the target for the build and update the file to point to the Android SDK used by the Jenkins executor(s). Here's what the build configuration looks like, with the relevant output from the Jenkins console:

Running multi-configuration build/test jobs makes continuous integration for Android development a practical reality, without the need to configure test environments and schedule runs manually. Every time you make changes to the code, you know that those changes will be tested across the huge range of devices, locales, settings and environments that you will need to support.

Mark Prichard, Senior Director of Product Management


Stay up to date

We'll never share your email address and you can opt out at any time, we promise.