Painless Travis CI/CD for Android Project

Dmitry Si
4 min readApr 27, 2017

--

Modern software development is far more “user”-friendly than it used to be. GitHub, Heroku, and the vast Fabric family of tools make code-review easy, deploy smooth, and health monitoring effortless. And when it comes to continuous integration, there is an easy solution as well. Travis is going to replace awkward Jenkins and Bamboo, and hyper-functional TeamCity with a familiar “show me what to build, and I’ll find the best solution.” But unlike Node.js/Python/Rails projects, it just doesn’t work that way for Android. If you still want your fancy new mobile projects to be continuously tested and your pull-requests to be checked but you do not want to dedicate the entire evening resolving Travis issues, here is the tutorial.

To make Travis work, you need to add a simple .travis.yml configuration file to the project’s root folder and push it to GitHub. GitHub integration is as simple as one-two-click, and there is a sample of the Android config which is already obsolete, so you have to update it.

The first thing you need to know about Travis is that it doesn’t build Android in the MacOS environment at the moment, and for Linux Oracle’s Java is not the default, so let’s start by changing from

language: android

to

language: android
jdk: oraclejdk8

Secondly, if you want your build tools version fresh and relevant to supported android version, I recommend you store that version as a constant because you’ll need it in many places and I bet you’ll update the config much more often than Travis doc is updated. So, your next step is

env: 
global:
- ANDROID_API_LEVEL=25
- ANDROID_BUILD_TOOLS_VERSION=25.0.2

Thirdly, Travis will not resolve dependencies for you like, for example, Heroku does for Python modules, so here we’ll use our variables. Let’s add all the main modules we’re going to use:

android:
components:
- tools
- platform-tools
# The BuildTools version used by your project
- build-tools-$ANDROID_BUILD_TOOLS_VERSION
# The SDK version used to compile your project
- android-$ANDROID_API_LEVEL
# Additional components
- extra-google-google_play_services
- extra-google-m2repository
- extra-android-m2repository
- addon-google_apis-google-$ANDROID_API_LEVEL

The names here are exactly the same as you can get running following command:

android list sdk --extended --no-ui --all

Fourthly, Google requires you to accept their license agreement before you can get their libraries and tools. Good news is that Travis can accept it for you by regexp, just add it under the android section:

licenses:
- 'android-sdk-preview-license-.+'
- 'android-sdk-license-.+'
- 'google-gdk-license-.+'

The bad news is that it will not work for several new libraries, such as the recently released ConstraintLayout. Well, don’t worry, I have a solution for you, as a manually accepted license can be exported to any machine, so copy the license folder from your $ANDROID_HOME/licenses to your project and keep it along with the code. Next, a couple of lines will export the license files from your source directory to the proper place, so Travis won’t get stuck at this step anymore (I gave my source folder the name google-licenses to make it more specific):

before_script:
- mkdir -p "$ANDROID_HOME/licenses"
- cp ./google-licenses/* "$ANDROID_HOME/licenses/"

And lastly: Travis uses command

gradle build connectedCheck

to build your project, perform lint checks, and execute your UI tests, which means you need to launch an emulator first after downloading it, running it, and waiting for it. There is a ready Travis script, but it is still unreliable. So let’s add this line:

script: - ./gradlew build check

It will override the default command, and Travis will only run lint and emulator independent unit-tests (I suggest you keep your gradlew with the source code as recommended). Now we are ready to go! Here is the full minimal working .tavis.yml file for you:

language: android
jdk: oraclejdk8
env:
global:
- ANDROID_API_LEVEL=25
- ANDROID_BUILD_TOOLS_VERSION=25.0.2
android:
licenses:
- 'android-sdk-preview-license-.+'
- 'android-sdk-license-.+'
- 'google-gdk-license-.+'
components:
- tools
- platform-tools
# The BuildTools version used by your project
- build-tools-$ANDROID_BUILD_TOOLS_VERSION
# The SDK version used to compile your project
- android-$ANDROID_API_LEVEL
# Additional components
- extra-google-google_play_services
- extra-google-m2repository
- extra-android-m2repository
- addon-google_apis-google-$ANDROID_API_LEVEL
before_script:
# Prepare pre-accepted licenses to not be promted at installation
- mkdir -p "$ANDROID_HOME/licenses"
- cp ./google-licenses/* "$ANDROID_HOME/licenses/"
script:
- ./gradlew build check

If you have no specific dependencies, you can omit before_script section, and if you’re brave enough to play with the emulator, you may want to add something like this

- sys-img-armeabi-v7a-google_apis-25

to the components and this

# Launch emulator before the execution
- echo no | android create avd --force -n test -t android-25 --abi google_apis/armeabi-v7a
- emulator -avd test -no-audio -no-window &
- android-wait-for-emulator
- adb shell input keyevent 82 &

to the before_script. Note that the create avd command uses different notation and that you cannot copy-paste the component name to it -

sys-img-armeabi-v7a-google_apis-25

will become

-t android-25 --abi google_apis/armeabi-v7a

You specify the Android version as the separated -t parameter, abi version as the -abi parameter, and additional parts such as Android Wear or Google API are listed as the abi prefix like google_apis/. The full list is available via the same command:

android list sdk --extended --no-ui --all

Enjoy your painless CI! If you want to check the complete example check it on GitHub

Originally published at https://distillery.com on April 27, 2017.

--

--

Dmitry Si
Dmitry Si

Written by Dmitry Si

Software developer. Most recently Android Java/Kotlin engineer. Former manager, desktop and embedded software creator. https://github.com/fo2rist/

No responses yet