One of the toughest things to do in life is get code into production. When developing Android APKs you can make use of the excellent Android Studio.

This works really well for single developers, but as soon as you have multiple developers or multiple testers, coders, and users, there comes a question of how do you distribute the Android binaries? How do you make sure that you have a single source of truth that everyone can deploy – not just a single laptop with all the bits configured?

You need Version Control

First Git and GitHub–no brainer for any kind of substantial development.

You need a CD Server

What is Continuous Delivery (CD)?

CD is a software engineering approach in which teams produce software in short cycles, ensuring that the software can be reliably released at any time. The rise of microservices, cloud native architectures has caused a corollary rise in continuous delivery practices. This is related to CI/CD that includes Continuous Integration (CI) – the practice of merging all developer working copies to a shared mainline several times a day.

Jenkins

This can get a bit more complicated as now you have to setup Jenkins which is one of the default CD Servers out there. There are others, but many start here and then move to other platforms once they outgrow Jenkins. If you are doing development involving more than one person, then Jenkins is required. You can self-host or there are paid Cloud versions available.

See my Jenkins setup post – here

Android Commandline tools

You will need the sdkmanager for installing Android packages (version compiling tools) which is part of the commandline-tools zip file. You no longer need the android-sdk package installed via apt – that is too old. These commandline-tools run the Android build tools from the commandline via the Jenkinsfile.

After you download the cmmdlinetools (I had to download them on windows and sftp the to the Jenkins Server)

  • Unzip the contents
  • Using the direct path install the tools via the command:
    • ./cmdline-tools/bin/sdkmanager --install "cmdline-tools;latest" --sdk_root=/home/vagrant/android_sdk
    • The --sdk_root is the directory where the new sdk tools will be installed to
  • Set the .bashrc to add the path to the sdkmanager to the system path
  • Set the Jenkins global settings from the Jenkins web console to find this path
    • Set ANDROID_SDK_HOME to the sdk_root you defined earlier
    • On Linux set JAVA_HOME to /usr

Once everything is set the output of --list_installed should look like below. Finally there is a permission issue to consider. In order for Jenkins to use the sdkmanager and write files – the sdkmanager would need to owned by jenkins:jenkins – but if you want to install packages – the files should be owned by your user. A few things can be done:

  • use sudo
  • chown -R jenkins:jenkins and then back to your own user
  • Though there has to be a better way to do this
sdkmanager --list_installed

######Output
  Path                 | Version      | Description                             | Location
  -------              | -------      | -------                                 | -------
  build-tools;28.0.3   | 28.0.3       | Android SDK Build-Tools 28.0.3          | build-tools/28.0.3
  cmake;3.6.4111459    | 3.6.4111459  | CMake 3.6.4111459                       | cmake/3.6.4111459
  cmdline-tools;latest | 7.0          | Android SDK Command-line Tools (latest) | cmdline-tools/latest
  emulator             | 31.2.10      | Android Emulator                        | emulator
  ndk;20.0.5594570     | 20.0.5594570 | NDK (Side by side) 20.0.5594570         | ndk/20.0.5594570
  patcher;v4           | 1            | SDK Patch Applier v4                    | patcher/v4
  platform-tools       | 33.0.2       | Android SDK Platform-Tools              | platform-tools

Commands

sdkmanager --install 'cmake;3.6.4111459'
sdkmanager --install 'ndk;20.0.5594570'
sdkmanager --install 'build-tools;28.0.3'
sdkmanager --install 'platforms;android-28'

Jenkins Project

  • Choose Multi-pipeline
  • Setup credentials
    • (Use Personal Access Token – add URL and validate)
  • Include a file named: Jenkinsfile in the root of your Android Project repo.
    • This Jenkinsfile will automatically be scanned for by Jenkins
    • Is essentially a template file that will call the commands you need to build you Android Project

Here is a sample Jenkinsfile. The file will execute from the root directory of your repository, will change directory to the location of the gradlew file, and then execute your build. Here the build is defined as assembleRelease – it could also be defined assembleDebug depending on the life-cycle of the app.

// https://www.jenkins.io/doc/book/pipeline/jenkinsfile/
pipeline {
    agent any

stages {
    stage('Build')  {
          steps {      
                dir("ap-final-app") {
                sh 'chmod +x ./gradlew'
                sh './gradlew assembleRelease'
                }
        }
    }    
        stage('Test') {
            steps {
                echo 'Testing..'
            }
        }
    }
}

The dir directive

In your Jenkinsfile, you have to understand pathing. The Jenkinsfile executes in the root directory, but if your gradlew executable is in a different directory Jenkins won’t find it. You need to add a dir() directive–essentially a cd command to get to the right directory to execute your gradlew command.

Without being in the correct directory you can get build errors such as the one below, which lead you on a wild goose chase. The real problem was you were trying to execute something and you were in the wrong directory (the computer doesn’t know that).

groovy.lang.MissingPropertyException: No such property: assembleDebug for class: groovy.lang.Binding
  at groovy.lang.Binding.getVariable(Binding.java:63)
  at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:251)

Use Hub for deploying releases

Now that you have successfully built an APK on a build server using Jenkins, you need to get this artifact deployed to the Releases tab on GitHub. The Releases tab allows for a central location to release artifacts that can be downloaded and then side-loaded onto your Android device.

This requires a third part tool from GitHub called: Hub.


# A simple Hub file
#!/bin/bash

TODAY="v$(date +%Y-%m-%d.%H%M%S)"

# GITHUB_TOKEN is defined in Jenkins Configuration to provide the Jenkins User with the Credentials to authenticate to Github
# Using HUB from Github - https://github.com/github/hub

# Release Publishing

hub release create \
       -a path-to-file-to-release \
       -m "Name of release" \
       -m "Release note" \
       YourTagNameHere

Conclusion

Automation is the key. Yet Operating systems and compiler tools were not designed for automated creation and deployment of apps. This is a great opportunity but takes some time to put together. But once it is together it can speed deployment and get your Android App into you and your development teams hands.