< Back to Blog

Painless Travis CI/CD for Android Project

CI for Android Project

Modern software development is far more “user”-friendly to developers than it used to be. GitHub, Heroku, and the huge Fabric family of tools make code review easy, deploy painless, and health monitoring pleasant. 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 do the rest 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 pull-requests checked automatically without wanting to spend your entire evening resolving Travis issues, we at Distillery have a solution.

So, 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 certain 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 just 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 the

gradle build connectedCheck

command 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

Basically, 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 help setting up your Travis or any other continuous integration tool, our DevOps team will be happy to help.


BACK TO TOP >