Further automation

Most modern continuous integration systems support Gradle, either by default or through a plugin. This means that instead of just building your app or library, you can create all kinds of Gradle tasks to further automate the build. The advantage of defining extra build steps with Gradle tasks, instead of in the CI system itself is that the extra build steps become much more portable. It is easy to run a custom Gradle task on your development machine. A custom Jenkins build step, on the other hand, is impossible to run without having Jenkins installed. Having extra build steps in a certain CI system also makes it harder to switch to a different CI system. Gradle tasks can also easily be ported to different projects. In this section, we will look at a few ways to further automate building and deploying apps and libraries, using Gradle tasks and plugins.

The SDK manager plugin

An issue you might run into at some point is that the Android SDK on the build server is not up to date. When you update the SDK version for your app or library, you also need to install the new SDK on the build server. If you have multiple build agents, this becomes a real hassle.

Thanks to community efforts, there is a Gradle plugin that takes care of checking whether the build depends on an Android SDK version that is not present. If the SDK is not present, the plugin will download it automatically.

The SDK manager plugin will download not only the compilation SDK specified in the build configuration file, but also the correct version of the build tools and platform tools. If your project has a dependency on the support library or Google Play Services, the plugin will download the specified version of those as well.

The SDK manager plugin is an open source plugin, you can find the source code for it on GitHub (https://github.com/JakeWharton/sdk-manager-plugin).

Running tests

If you want to run unit tests (JUnit or Robolectric) during the build process on the build server, you simply need to add the corresponding tasks to the Gradle execution. If you want to run any functional tests, you will need an emulator to install your app on, so you can run the tests with gradlew connectedAndroidTest.

The simplest option for running an emulator is to just launch an emulator on the build server, and keep it open all the time. Unfortunately, this is not an optimal solution, because the Android emulators are quite prone to random crashes, especially when you keep them open for multiple days.

If you are using Jenkins, there is a plugin called Android Emulator Plugin (https://wiki.jenkins-ci.org/display/JENKINS/Android+Emulator+Plugin) that can be configured to launch an emulator for every build of your app or library. TeamCity also has a lively plugin ecosystem, and there is a plugin called Android Emulator that helps setting up an emulator in the same way as the Jenkins plugin. You can find it, along with other TeamCity plugins, on the official TeamCity plugins page (https://confluence.jetbrains.com/display/TW/TeamCity+Plugins).

Travis CI has the ability to start an emulator, but this is an experimental functionality. If you want to try it anyway, add this snippet to your .travis.yml configuration file to launch an Android emulator during your Travis builds:

# Emulator Management: Create, Start and Wait
before_script:
  - echo no | android create avd --force -n test -t android-22 --abi armeabi-v7a
  - emulator -avd test -no-skin -no-audio -no-window &
  - android-wait-for-emulator
  - adb shell input keyevent 82 &

The android-wait-for-emulator instruction tells Travis to wait for the emulator to start. When the emulator is booted, adb shell input keyevent 82 & is executed to unlock the screen. After that, you can just tell Gradle to run the tests.

Continuous deployment

To help developers with automatic deployment of Android apps, Google released the Google Play Developer API, an API for pushing APKs to Google Play programmatically (https://developers.google.com/android-publisher). This API removes the need for you to open a browser, log in to Google Play, and upload APKs using the web interface. Instead of creating your own publishing script based on the Google Play Developer API, you can use one of the many plugins to push APKs to Google Play directly after a successful build, straight from the build system.

There is a Jenkins plugin called Google Play Android Publisher (https://wiki.jenkins-ci.org/display/JENKINS/Google+Play+Android+Publisher+Plugin) that can handle this for you. A better option, though, is to use a Gradle plugin, so that you can execute the publishing task from any device and any kind of continuous integration system. Some people in the Android community created a Gradle plugin built around the Google Play Developer API that enables you to configure the entire publishing process. You can find the Gradle Play Publisher Gradle plugin source code on GitHub (https://github.com/Triple-T/gradle-play-publisher). It is also available through Maven Central or JCenter.

To start using this plugin, add this to your main build.gradle file:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.github.triplet.gradle:play-publisher:1.0.4'
    }
}

Then apply the plugin in your Android module's build.gradle file:

apply plugin: 'play'

When you apply the Gradle Play Publisher plugin to your build, you will have a few new tasks to your availability:

  • publishApkRelease uploads the APK and the recent changes
  • publishListingRelease uploads the descriptions and images
  • publishRelease uploads everything

If you have different build variants, you can also execute a variant-specific version of these tasks, for example, publishApkFreeRelease and publishApkPaidRelease.

To get access to the Google Play Developer API, you need to set up a service account. This setup is out of the scope of this book, but it is required if you want to use the Gradle Play Publisher plugin. To get started, follow the steps in the documentation for the Google Play Developer API at https://developers.google.com/android-publisher/getting_started.

Once you have created a service account, you can enter the credentials in your build configuration file like this:

play {
    serviceAccountEmail = 'serviceaccount'
    pk12File = file('key.p12')
}

The play block is for properties that are specific for the Gradle Play Publisher plugin. In addition to the service account credentials, you can also specify the track the APK should push to:

play {
    track = 'production'
}

The default track is alpha, but you can change it to beta or production instead.

Beta distribution

There are a lot of options for beta testing of Android apps, such as the beta track on the Google Play store itself. Another option is Crashlytics (https://crashlytics.com), which has a very nice integration with Gradle. The team at Crashlytics created a custom plugin that not only creates new Gradle tasks to publish builds to their platform, but also hooks into the Android plugin's tasks to handle ProGuard mapping.

To get started with Crashlytics, follow the steps on their website. Once you have set it up, it will start hooking into your builds. The Crashlytics plugin exposes a new task called crashlyticsUploadDistributionInternal that can be used to upload APKs to Crashlytics. To push a new version of your app, you first need to build it using the build or assemble tasks. Once the APK is ready, you can upload it to Crashlytics using the crashlyticsUploadDistributionInternal task. The Crashlytics plugin creates an upload task for every build variant in your project.

Thanks to the custom Gradle plugin, it is very easy for developers to get started with Crashlytics. It also makes it a breeze to upload your test builds to Crashlytics, because you just need to execute one extra task during the build process. This is a great example of how powerful the proper use of Gradle can be, and how a good Gradle plugin can make developers' lives a lot easier.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset