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.
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.
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.
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.
To sign and zipalign the APK we will need to change our
Fastfile by editing the
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
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. 🚀
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
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.jksfile 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.jkssomewhere 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.jksto 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
After that, you need to add the encoded key to a CircleCI environment variable named
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.
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
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
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.
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.
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
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 (
*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.
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.
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! 🚀