Improve CI build times on your Android project

How to improve Android build times using Travis CI - Coletiv Blog

At Coletiv we normally use Continuous Integration (CI) / Continuous Delivery (CD) in every project. It’s great once you have everything well configured, but to get there you have to spend too much time tweaking and testing your configurations in your CI service of choice. Believe me, I’ve had too many headaches with this, but finally, I was able to configure this in a way that I’m happy with.

The problem

There is a lack of good documentation and tutorials to help you set up your Android project. To start up, you’ll probably rely on examples given by other developers. At least that was the case for me, and that’s not a bad thing. I’m glad that there are other developers out there willing to help out, but most of the stuff that you find is either outdated or doesn’t fit your needs. Keep in mind that we’re currently using Travis-CI, but for what I could understand in my research, other services have the same problem.



With that in mind, our Android build times were reaching 20 minutes! That’s a lot of time lost in every pull request. And if you have more repositories set up in the same organization with no parallel builds, you’re probably blocking your colleagues’ builds, also wasting their time.

Trigger a build and pay close attention to the log until the end. Check what’s taking more time to run.

So the first thing you should do is identify what is causing this long build time on your project. Trigger a build and pay close attention to the log until the end. Check what’s taking more time to run. In our case, most of that time was spent on setting up the actually CI machine and on instrumentation tests, which are tests that run on physical devices and emulators.

Tip 1 — Check your config file for unneeded commands

Check this excerpt from our old config file:

android:
  components:
  - tools
  - platform-tools
  - tools
  - build-tools-25.0.3
  - build-tools-24.0.3
  - android-24
  - addon-google_apis-google-24
  - extra-google-google_play_services
  - extra-android-support
  - extra-google-m2repository
  - extra-android-m2repository
  - sys-img-armeabi-v7a-android-24
  licenses:
  - android-sdk-preview-license-.+
  - android-sdk-license-.+
  - google-gdk-license-.+
  - intel-android-extra-license.+

That seems like a lot of stuff needed only to build your Android app and to test it, right? The CI machine will download and install all that stuff! Do you really need all this?



Debug your build and check which commands you really need. Try to remove the components that you think you don’t need and test different configurations. Check if the build still passes. I know it’s not much to go on, but check out what we’ve achieved doing that.

env:
  global:
  - ANDROID_TARGET=android-28
  - ANDROID_BUILD_TOOLS_VERSION=28.0.3

android:
  components:
  - tools
  - build-tools-$ANDROID_BUILD_TOOLS_VERSION
  - $ANDROID_TARGET
  - extra-google-google_play_services
  - extra-android-support
  - extra

licenses:
- '.+'

Now we only install the tools for our target Android version and removed most of the add-ons and extras that weren’t needed.



If you paid attention you’ll note that we removed all system images and you’re asking yourself, how am I supposed to run the emulator now? You simply don’t! And this leads us to the next tip.

Tip 2 — Don’t run emulators in your CI machine

It is not possible to run x86 android emulators on most cloud CI platforms, so you’ll have to use an arm-based emulator, but the last android version that supports it is android-25. That requires you to install and configure that android version, slowing down your build, not to mention the precious time lost just creating and starting the emulator.



Even though, if you’re interested in going that way, check out this thread on the Travis community forum, where they talk about adding KVM support, and this article, where multiple emulator versions are tested.



But what I really want to propose is running your instrumentation tests somewhere else. We’ve started doing it with Firebase Test Lab since we’re already using Firebase on our projects. You have 10 tests/day for free on virtual devices.



If you’re interested to know how we’ve got it working with Travis here is the relevant parts of our config file:

before_script:
# Download and install gcloud cli to run firebase test commands
- wget https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-218.0.0-linux-x86.tar.gz
- tar zxf google-cloud-sdk-218.0.0-linux-x86.tar.gz google-cloud-sdk
- echo n | ./google-cloud-sdk/install.sh
- ./google-cloud-sdk/bin/gcloud auth activate-service-account --key-file dir-to-your-service-account-key.json
- ./google-cloud-sdk/bin/gcloud config set project your-project
- echo y | ./google-cloud-sdk/bin/gcloud components update
- echo y | ./google-cloud-sdk/bin/gcloud components install beta

script:
- chmod +x gradlew
- ./gradlew assembleDebug
- ./gradlew assembleDebugAndroidTest
# Run test on a Pixel 2 with Android 28 in english and in portrait
- ./google-cloud-sdk/bin/gcloud beta firebase test android run --use-orchestrator --type instrumentation --app dir-to-your-apk/your-app.apk --test dir-to-your-test-apk/your-test-app.apk --device model=walleye,version=28,locale=en,orientation=portrait

Our instrumentation tests now run in less than 150 seconds. Previously that time alone wasn’t enough to just start the emulator. That’s an amazing improvement.

Tip 3 — Only run certain commands on a given branch or on a pull request

There are commands that you can run only on a certain branch. For instance, you might want to deploy your app only when there is a merge into master. Also, you certainly don’t want to run your instrumentations tests on every commit. You should only run them on pull requests. That way you can shave some precious minutes off of your build.



On Travis-CI you can do it like this:

- if [ $TRAVIS_BRANCH == 'master' ]; then
  your-command-here;
  fi
- if [ $TRAVIS_PULL_REQUEST != false ]; then
  your-command-here;
  fi

Profit

Following these tips, our build times were reduced from over 20 minutes to just under 8 minutes! That’s amazing, right? Hope that you can achieve the same results! If you have any questions, drop a comment below and I will try to help you out.

Thank you for reading! 😊

Thank you so much for reading, it means a lot to us! Also don’t forget to follow Coletiv on Twitter and LinkedIn as we keep posting more and more interesting articles on multiple technologies.

In case you don’t know, Coletiv is a software development studio from Porto specialised in Elixir, iOS, and Android app development. But we do all kinds of stuff. We take care of UX/UI design, web development, and even security for you.

So, let’s craft something together?