Language Guide: Android
This document describes how to set up an Android project on CircleCI in the following sections.
- Sample configuration
- Config walkthrough
- Docker images
- Testing with Firebase Test Lab
- Deployment
- Troubleshooting
Overview
This guide provides an introduction to Android development on CircleCI.
If you are looking for a .circleci/config.yml
template for Android,
see the Sample Configuration section of this document.
Note: We now have an Android machine image available in preview on CircleCI Cloud that supports x86 Android emulators and nested virtualization. Documentation on how to access it is available here. Another way to run emulator tests from a job is to consider using an external service like Firebase Test Lab. For more details, see the Testing With Firebase Test Lab section below.
Prerequisites
This guide assumes the following:
- You are using Gradle to build your Android project. Gradle is the default build tool for projects created with Android Studio.
- Your project is located in the root of your VCS repository.
- The project’s application is located in a subfolder named
app
.
Sample configuration
version: 2
jobs:
build:
working_directory: ~/code
docker:
- image: circleci/android:api-30-alpha
auth:
username: mydockerhub-user
password: $DOCKERHUB_PASSWORD # context / project UI env-var reference
environment:
JVM_OPTS: -Xmx3200m
steps:
- checkout
- restore_cache:
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
# - run:
# name: Chmod permissions #if permission for Gradlew Dependencies fail, use this.
# command: sudo chmod +x ./gradlew
- run:
name: Download Dependencies
command: ./gradlew androidDependencies
- save_cache:
paths:
- ~/.gradle
key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}
- run:
name: Run Tests
command: ./gradlew lint test
- store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/
path: app/build/reports
destination: reports
- store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/
path: app/build/test-results
# See https://circleci.com/docs/2.0/deployment-integrations/ for deploy examples
Config walkthrough
We always start with the version.
version: 2
Next, we have a jobs
key. Each job represents a phase in your Build-Test-Deploy process. Our sample app only needs a build
job, so everything else is going to live under that key.
In each job, we have the option of specifying a working_directory
. This is the directory into which our code will be checked out, and this path will be used as the default working directory for the rest of the job
unless otherwise specified.
jobs:
build:
working_directory: ~/code
Directly beneath working_directory
, we can specify container images under a docker
key.
docker:
- image: circleci/android:api-25-alpha
auth:
username: mydockerhub-user
password: $DOCKERHUB_PASSWORD # context / project UI env-var reference
We use the CircleCI-provided Android image with the api-25-alpha
tag. See Docker Images below for more information about what images are available.
Now we’ll add several steps
within the build
job.
We start with checkout
so we can operate on the codebase.
Next we pull down the cache, if present. If this is your first run, or if you’ve changed either of your build.gradle
files, this won’t do anything. We run ./gradlew androidDependencies
next to pull down the project’s dependencies. Normally you never call this task directly since it’s done automatically when it’s needed, but calling it directly allows us to insert a save_cache
step that will store the dependencies in order to speed things up for next time.
Then ./gradlew lint test
runs the unit tests, and runs the built in linting tools to check your code for style issues.
We then upload the build reports as job artifacts, and we upload the test metadata (XML) for CircleCI to process.
Docker images
For convenience, CircleCI provides a set of Docker images for building Android apps. These pre-built images are available in the CircleCI org on Docker Hub. The source code and Dockerfiles for these images are available in this GitHub repository.
The CircleCI Android image is based on the openjdk:11-jdk
official Docker image, which is based on buildpack-deps. The base OS is Debian Jessie, and builds run as the circleci
user, which has full access to passwordless sudo
.
API levels
We have a different Docker image for each Android API level. To use API level 24 (Nougat 7.0) in a job, you should select circleci/android:api-24-alpha
.
Customizing the images
We welcome contributions on our GitHub repo for the Android image. Our goal is provide a base image that has most of the tools you need; we do not plan to provide every tool that you might need.
To customize the image, create a Dockerfile that builds FROM
the circleci/android
image. See Using Custom-Built Docker Images for instructions.
You can also use the CircleCI Android Orb to select your desired Android SDK and NDK.
React Native projects
React Native projects can be built on CircleCI 2.0 using Linux, Android and macOS capabilities. Please check out this example React Native application on GitHub for a full example of a React Native project.
Testing with Firebase Test Lab
To use Firebase Test Lab with CircleCI, first complete the following steps.
-
Create a Firebase project. Follow the instructions in the Firebase documentation.
-
Install and authorize the Google Cloud SDK. Follow the instructions in the Authorizing the Google Cloud SDK document.
Note: Instead of
google/cloud-sdk
, consider using an Android convenience image, which includesgcloud
and Android-specific tools. -
Enable required APIs. Using the service account you created, log into Google and go to the Google Developers Console API Library page. Enable the Google Cloud Testing API and the Cloud Tool Results API by typing their names into the search box at the top of the console and clicking Enable API.
In your .circleci/config.yml
file,
add the following run
steps.
-
Build the debug APK and test APK. Use Gradle to build two APKs. To improve build performance, consider disabling pre-dexing.
-
Store the service account. Store the service account you created in a local JSON file.
-
Authorize
gcloud
. Authorize thegcloud
tool and set the default project. -
Use
gcloud
to test with Firebase Test Lab. Adjust the paths to the APK files to correspond to your project. -
Install
crcmod
and usegsutil
to copy test results data.crcmod
is required to usegsutil
. Usegsutil
to download the newest files in the bucket to the CircleCI artifacts folder. Be sure to replaceBUCKET_NAME
andOBJECT_NAME
with project-specific names.
version: 2
jobs:
test:
docker:
- image: circleci/android:api-28-alpha # gcloud is baked into this image
auth:
username: mydockerhub-user
password: $DOCKERHUB_PASSWORD # context / project UI env-var reference
steps:
- run:
name: Build debug APK and release APK
command: |
./gradlew :app:assembleDebug
./gradlew :app:assembleDebugAndroidTest
- run:
name: Store Google Service Account
command: echo $GCLOUD_SERVICE_KEY > ${HOME}/gcloud-service-key.json
- run:
name: Authorize gcloud and set config defaults
command: |
sudo gcloud auth activate-service-account --key-file=${HOME}/gcloud-service-key.json
sudo gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
- run:
name: Test with Firebase Test Lab
command: >
sudo gcloud firebase test android run \
--app <local_server_path>/<app_apk>.apk \
--test <local_server_path>/<app_test_apk>.apk \
--results-bucket cloud-test-${GOOGLE_PROJECT_ID}
- run:
name: Install gsutil dependency and copy test results data
command: |
sudo pip install -U crcmod
sudo gsutil -m cp -r -U `sudo gsutil ls gs://[BUCKET_NAME]/[OBJECT_NAME] | tail -1` ${CIRCLE_ARTIFACTS}/ | true
For more details on using gcloud
to run Firebase,
see the official documentation.
Deployment
See the Deploy document for examples of deploy target configurations.
Troubleshooting
Handling out of memory errors
You might run into out of memory (oom) errors with your build. To get acquainted with the basics of customizing the JVM’s memory usage, consider reading the Debugging Java OOM errors document.
If you are using Robolectric for testing you may need to make tweaks to gradle’s
use of memory. When the gradle vm is forked for tests it does not receive
previously customized JVM memory parameters. You will need to supply Gradle with
additional JVM heap for tests in your build.gradle
file by adding android.testOptions.unitTests.all { maxHeapSize = "1024m" }
. You can also add all { maxHeapSize = "1024m" }
to your existing Android config block, which could look like so after the addition:
android {
testOptions {
unitTests {
// Any other configurations
all {
maxHeapSize = "1024m"
}
}
}
If you are still running into OOM issues you can also limit the max workers for
gradle: ./gradlew test --max-workers 4
Disabling pre-dexing to improve build performance
Pre-dexing dependencies has no benefit on CircleCI. To disable pre-dexing, refer to this blog post.
By default, the Gradle Android plugin pre-dexes dependencies. Pre-dexing speeds up development by converting Java bytecode into Android bytecode, allowing incremental dexing as you change code. CircleCI runs clean builds, so pre-dexing actually increases compilation time and may also increase memory usage.
Deploying to Google Play Store
There are a few third-party solutions for deploying to the Play Store from your CI build. Gradle Play Publisher enables you to upload an App Bundle/APK as well as app metadata. It’s also possible to use Fastlane with Android.