Android Continuous Integration using Fastlane and CircleCI 2.0 — Part III

The ultimate guide to automate the builds, tests and deploys of your Android application.

Photo by SpaceX on Unsplash

Hello again! 😃 We have finally come to the end of this series of blog posts. If you haven’t had the opportunity to give a try to the first and second parts, now it’s the time (most of the following steps assume you use the same Fastlane and CircleCI configurations that are present in these blog posts). So, last but not least, we will show you how to continuous deploy your app in the Play Store using Fastlane and CircleCI.

Setup Supply

Fastlane uses a tool called supply to deploy your binaries to the Play Store. And, the first thing that you have to do is to setup supply to allow its access to your Play Store account. To do that, you need to follow all these steps.

Now, you should be able to move to the next part. 😎

Sign and Zipalign

Before releasing your app to the Play Store you need to digitally sign your APK. This is a required step since every APK needs to contain a certificate in order to verify it’s authenticity when the app is installed.

Make sure there are no fake APKs!

Moreover, you should also Zipalign it before the release. This step will perform some important optimisations to your app leading to a reduction in the RAM consumed.

Locally

To sign and zipalign the APK we will need to change our Fastfile by editing the assemble_build lane.

As you can see, we have some properties that are passed to the gradle task if we are assembling a release APK. These properties contain your private key info that will be used to sign your app. If you don’t have a key yet, you need to create a new one by running:

keytool -genkey -v -keystore keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias key_alias

You will be prompted to enter your store_password and key_password. After that, edit your lane to contain your key info.

Now it’s time to build your release APK:bundle exec fastlane assemble_build release:true. 🚀

Remotely

To avoid having your private key info hardcoded in your code, you can modify your lane to use environment variables.

Now, you need to set your STORE_PASSWORD, KEY_ALIAS and KEY_PASSWORD in the CircleCI environment variables. Nevertheless, we still need to find a way to properly get the keystore.jks file in CircleCI.

Let’s give a look at some of our options:

  • Add your keystore.jks file to your repo. This is the easiest way, but if you have an open source project you don’t want to have your private key public.
  • Add your keystore.jks somewhere in the cloud and download it. This approach works, but the main question is: Is your key in a secure and safe place? 🤔 Moreover, do we want to download the key every time we need to deploy a new release APK?
  • Convert your keystore.jks to base64, add it as an environment variable and decode it in CircleCI. With this approach, we have our key encoded in the CircleCI server (it should be safe) and we only need to decode it when we want to deploy a new release.

Following the third approach you firstly need to convert your keystore.jks to base64. To do that, simply run base64 keystore.jks.

After that, you need to add the encoded key to a CircleCI environment variable named KEYSTORE.

So, it’s time to implement the command to decode the key. Open your .circleci/config.yml file and create a Reference like the one below.

What we are doing here is to decode the KEYSTORE environment variable and output the result to two keystore.jks files (yes, gradle will need this file in the root directory of your project and inside your app folder ¯\_(ツ)_/¯). The >/dev/null is just there to avoid outputting the result to the console.

For now, this is all you need to change in your CircleCI configuration file. We will show you how to use this reference in a bit. 😎

Shrink code and resources

Another important step to do before releasing your app is to shrink your code and your resources. This will reduce your APK size significantly and impact the time that the app takes to load, the memory and the power consumption. And, of course, reduces the time that your app takes to be downloaded from the Play Store.

Shrink code

To shrink your code you need to use ProGuard. This will ensure that your unused classes, methods, etc are removed. It also optimizes your application bytecode and obfuscates the code. How awesome is that? 😃

To use ProGuard, modify your build.gradle and add the code below.

Note: When using ProGuard some libraries and even your code can need specific rules to work properly. Make sure you add the needed rules to your proguard-rules.pro file.

Shrink resources

First, resource shrinking only works together with code shrinking and you can enable it with a Gradle plugin. To do that, simply add shrinkResources true to your build.gradle file.

Resource shrinking runs after code shrink and will remove all the resources that your app isn’t using. This is very important specially if you use many libraries that contain resources that you don’t need at all.

Fastfile

After configuring everything needed to create a release APK, it’s time to create a lane to deploy your app to the Play Store. To do that, edit your Fastfile and copy the code below.

Set the build type to Release. Then, we will assemble the application to create a release APK. To finish, we just need to upload the APK to the Play Store. For more info, you can verify all the available parameters for the upload_to_play_store action here.

CircleCI

Now that Fastlane is able to deploy a release version of an app, we need to integrate it with CircleCI.

References

Do you still remember when you configured the supply tool? You created a file with the credentials to access the Google Play Store. In CircleCI you need to add the content of that file to an environment variable called GOOGLE_PLAY_KEY and create a Reference that will create that file for you.

Note: Don’t forget to change the file name in the code above or change the file name that you have in your Appfile.

Jobs

Now, we will finally create a job to deploy our app to the Play Store. Something like this:

As you might have noticed, all the first steps are exactly the same that we have in all the other jobs created in the last blog post.

Other than that, we are using the two references created before (*decode_android_key and *create_google_play_key), that are needed to create a release APK and to deploy the app to the Google Play Store.

Then, run the Fastlane lane responsible to deploy your app.

Finally, we store the released APK and the outputs from ProGuard in the CircleCI artifacts.

Workflows

To finish our CircleCI setup we need to add our job to the workflow.

Above, we run the unit tests, followed by the instrumentation tests. After that, if the current branch is the production one, we will run the deploy_play_store job to deploy the new version to the Google Play Store.


And TADA. 🎉 We are officially done!

The final Fastfile can be found here and the CircleCI config.yml here.

I really hope this series of posts can be used by you as a base for continuous integration and deployment of your Android apps.

Again, we are more than welcome to listen, learn and improve with your suggestions. So, if you have any other ideas, approaches or solutions share them with us. We would love to ear from you. 😀

Happy coding! 🚀

References: