Build your release APK with CircleCI

This entry is about Android development.

It has been quite long since the last time I wrote an actual technical blog entry. Then I was too much busy being inactive, and I did change my job. Now I am in a position that I have learnt every day. I should have written this post a year ago in order to summarize the knowledge I got, but whenever I type a few words, I feel exhausted. This time is my big try. *hat off*

I assume that you are familiar with:
- Gradle, a build system where you can write scripts to automate your tasks, in the scope of this entry, Android build/test tasks.
- Test-driven development (TDD), a software development process in which test cases are written before you code; or at least when you finished coding, the test cases are finished also.
- Continuous Integration (CI), a development practice that requires you to integrate code into a shared repository several times a day.

 The combination of Gradle, TDD and CI gives a result that every time you push code into a repository, it will automatically execute your Gradle script to build and run test cases on a specific environment to check you code.

There are several CI services, such as TravisCI, Shippable, Snap-CI, CircleCI, GreenHouseCI (AFAIK, this service targets mobile developing)... Each of them give you a set of commands to control the Integration process. If you want a certain condition of the virtual machine, or some pre-process steps... you must describe in a YAML file like ".travis.yml" for TravisCI or "circle.yml" for Circle CI.

The one my company chooses is CircleCI, so it is the service I have the most experiences and that is the reason why I put it into the post entry title :))

The entry will consist of 2 parts: Setup Circle CI and Write a Gradle task to be executed on CircleCI.

Setup Circle CI

The process is simple, first you have to have access to a repository, e.g: GitHub.
It's kinda simple so you may read it before somewhere on the internet.

  1. Click on the upper right hand Log In link to sign in to CircleCI with your GitHub account credentials.
  2. On the left-hand side menu, select the Add Projects menu option.
  3. On the Add Projects page, under the first section, click the suitable item, it could be your account or an organization that you are a member of.
  4. In the second section of the Add Projects page, filter or scroll for your project repository. 
  5. Click the Build Project button beside the repository name. By clicking this button, you are now following the project, click Unfollow project to undo this action, after that CircleCI will not run any time you push code to your GitHub repo.
My CircleCI "Add Projects" page with some of my project are followed.
Now CircleCI will install dependencies and start to build. On the Dashboard page, the side bar will load with all of the branch activities for that project.

Remember when you can not follow a project:
If you’re not an admin, invite a user with permissions to CircleCI, and have them follow the project first.
- CircleCI -

Because you have not uploaded the modified configuration file, CircleCI will install the SDK in its default config and then, if you have a Gradle wrapper in the root of your repository, it’ll automatically run the default command  

./gradlew test

Finally, add a file name "circle.yml" to the root directory of your project, it will be the place where you put your command to make CircleCI do what you need.
For a very simple guide of what should we write in this kind of file, please read more here: Test Android Applications - Circle CI. In this entry, I will only mentioned the overridden "test" part of the "circle.yml" file

Write a Gradle task to build release APK

There are two approaches to building in release mode: build an unsigned package in release mode and then manually sign and align the package, or allow the build script to sign and align the package for you. This part is showing you the second approach.

1. Create your own keystore

Please take a look at this tip to know how to generate a RSA 2048 key.

2. Add signing configuration to build file

After generating your keystore file, you will obtain 2 passwords, storePassword and keyPassword. It is not good if you put these passwords into the build file, so create environment variables for them, for example KSTOREPWD and KEYPWD.

Now copy your keystore file into app module of your project and edit the app's build.gradle file:

android {
    signingConfigs {
        release {
            storeFile file("myname.keystore")
            storePassword System.getenv("KSTOREPWD")
            keyAlias "MyKeyAlias"
            keyPassword System.getenv("KEYPWD")
    buildTypes {
        release {
            signingConfig signingConfigs.release

3. Add actions to circleci.yml

After running the tests, invoke the assembleRelease build task.

    - ./gradlew assembleRelease -PdisablePreDex

After CircleCI finishes, you should append $CIRCLE_BUILD_NUM to the apk file name, then move your resulting apk to $CIRCLE_ARTIFACTS so that you could deliver them.

Because there may be several resulting apk files, you should use the commands below:

      # copy the build outputs to artifacts
      - cp -r $APP_HOME/build/outputs $CIRCLE_ARTIFACTS
      # rename the apks
      - for f in "$CIRCLE_ARTIFACTS/outputs/apk"/*.apk; do mv "$f" "${f%.*}-$CIRCLE_BUILD_NUM.${f##*.}";done

I think now it is enough for you to handle all the signing and zipaligning in release mode. If your project runs successfully on CircleCI, in the artifact directory, you will find your apk(s), signed and aligned.


Popular posts from this blog

How to wrap a C# library for using in Java, a folk tale about an idiot coding at midnight.