Android application
You can build and test Android applications using a Linux or Mac platform on Harness Cloud, a self-hosted Kubernetes cluster, or a local runner build infrastructure.
This guide assumes you've created a Harness CI pipeline. For more information about creating pipelines, go to:
If you don't have a Harness account yet, you can create one for free at app.harness.io.
Specify architecture
- Harness Cloud
- Self-hosted
You can build and test Android apps on a Linux or Mac platform on Harness Cloud build infrastructure.
- Linux
- macOS
stages:
- stage:
name: Build
identifier: Build
type: CI
spec:
cloneCodebase: true
platform:
os: Linux
arch: Amd64
runtime:
type: Cloud
spec: {}
To use M1 machines with Harness Cloud, use the Arm64
architecture.
stages:
- stage:
name: build
identifier: build
type: CI
spec:
cloneCodebase: true
platform:
os: MacOS ## selects macOS operating system
arch: Arm64 ## selects M1 architecture
runtime:
type: Cloud
spec: {}
If you need to use Intel-based architecture, Rosetta is pre-installed on Harness Cloud's M1 machines. If you need to use it, add the prefix arch -x86_64
to commands in your scripts. Keep in mind that running apps through Rosetta can impact performance. Use native Apple Silicon apps whenever possible to ensure optimal performance.
You can build Android apps on a Linux or Mac platform on self-hosted build infrastructures, including Kubernetes clusters, VMs, and local runners.
- Linux
- macOS
This example sets up a Linux platform on a Kubernetes cluster build infrastructure.
stages:
- stage:
name: build
identifier: build
description: ""
type: CI
spec:
cloneCodebase: true
infrastructure:
type: KubernetesDirect
spec:
connectorRef: YOUR_KUBERNETES_CLUSTER_CONNECTOR_ID
namespace: YOUR_NAMESPACE
automountServiceAccountToken: true
nodeSelector: {}
os: Linux
To configure a self-hosted macOS build infrastructure, go to Set up a macOS VM build infrastructure with Anka Registry or Set up a local runner build infrastructure.
This example uses a VM build infrastructure:
stages:
- stage:
name: build
identifier: build
description: ""
type: CI
spec:
cloneCodebase: true
infrastructure:
type: VM
spec:
type: Pool
spec:
poolName: YOUR_VM_POOL_NAME
os: MacOS
If you need to use Intel-based architecture and Rosetta is not already installed on your build infrastructure machines, you can use a Run step to install this dependency. Keep in mind that running apps through Rosetta can impact performance. Use native Apple Silicon apps whenever possible to ensure optimal performance.
Install dependencies
- Harness Cloud
- Self-hosted
Many Android packages, such as command-line tools and an emulator, are already installed on Harness Cloud Linux machines. For more information about preinstalled tools and libraries, go to the Harness Cloud image specifications.
Use Run steps to install dependencies in the build environment.
- step:
type: Run
identifier: dependencies
name: dependencies
spec:
shell: Sh
command: |-
bundle update
Use Run steps to install dependencies in the build environment.
- step:
type: Run
identifier: dependencies
name: dependencies
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-30-v1.7.0
shell: Sh
command: |-
npm install -g firebase-tools
gem install fastlane
bundle exec fastlane add_plugin load_json
bundle exec fastlane add_plugin increment_version_code
bundle exec fastlane add_plugin firebase_app_distribution
Cache dependencies
Add caching to your stage.
- Harness Cloud
- Self-hosted
Use Cache Intelligence by adding caching
to your stage.spec
.
- stage:
spec:
caching:
enabled: true
paths:
- YOUR_CACHE_PATH
sharedPaths:
- YOUR_CACHE_PATH
Cache Intelligence supports Gradle. If you're using Gradle and your dependencies are stored in the default location for Gradle, you don't need to include paths
or sharedPath
. For example:
- stage:
spec:
caching:
enabled: true
With self-hosted build infrastructures, you can:
Here's an example of a pipeline with Save Cache to S3 and Restore Cache from S3 steps. It also includes a Run step that creates the .ipa
archive with xcodebuild archive
and xcodebuild --exportArchive
.
steps:
- step:
type: RestoreCacheS3
name: Restore Cache From S3
identifier: Restore_Cache_From_S3
spec:
connectorRef: AWS_Connector
region: us-east-1
bucket: your-s3-bucket
key: cache-{{ checksum "package.json" }} ## Example cache key based on checksum.
archiveFormat: Tar
- step:
type: Run
...
- step:
type: SaveCacheS3
name: Save Cache to S3
identifier: Save_Cache_to_S3
spec:
connectorRef: AWS_Connector
region: us-east-1
bucket: your-s3-bucket
key: cache-{{ checksum "package.json" }} ## Example cache key based on checksum.
sourcePaths:
- "YOUR_CACHE_PATH"
archiveFormat: Tar
Build and run tests
You can use Run or Run Tests steps to run tests in Harness CI.
If you're using Kotlin, you can improve your unit test times with Harness' Test Intelligence feature.
- Harness Cloud
- Self-hosted
- step:
type: Run
name: build and test
identifier: build_and_test
spec:
shell: Sh
command: |-
./gradlew test assemble -YOUR_PROJECT
./gradlew testDebug
If you want to view test results in Harness, make sure your test commands produce reports in JUnit XML format and that your steps include the reports
specification.
- step:
type: Run
name: build and test
identifier: build_and_test
spec:
shell: Sh
command: |-
./gradlew test assemble -YOUR_PROJECT
./gradlew testDebug
reports:
type: JUnit
spec:
paths:
- "*/build/test-results/.*xml"
- step:
type: Run
name: Test
identifier: test
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-30-v1.7.0
shell: Sh
command: |-
./gradlew test assemble -YOUR_PROJECT
./gradlew testDebug
If you want to view test results in Harness, make sure your test commands produce reports in JUnit XML format and that your steps include the reports
specification.
- step:
type: Run
name: Test
identifier: test
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-30-v1.7.0
shell: Sh
command: |-
./gradlew test assemble -YOUR_PROJECT
./gradlew testDebug
reports:
type: JUnit
spec:
paths:
- "*/build/test-results/.*xml"
Specify version
- Harness Cloud
- Self-hosted
Android packages, including Android SDK tools and and fastlane, are pre-installed on Harness Cloud machines. For details about all available tools and versions, go to Platforms and image specifications.
- step:
type: Run
name: android version
identifier: android_version
spec:
shell: Sh
command: |-
fastlane init
fastlane tests
If you need to install additional versions, use a Run step. These examples use faberNovel/docker-android and fastlane.
Use one version
- step:
type: Run
name: android version
identifier: android_version
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-30-v1.7.0
shell: Sh
command: |-
fastlane init
fastlane tests
Use multiple versions
- Add the matrix looping strategy configuration to your stage.
- stage:
strategy:
matrix:
androidVersion:
- 30
- 31
- 33
- Reference the matrix variable in the
image
field of your steps.
- step:
type: Run
name: android Version
identifier: android_version
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-<+ stage.matrix.androidVersion >-v1.7.0
shell: Sh
command: |-
fastlane init
fastlane tests
Specify the desired Android Docker image tag in your steps. There is no need for a separate install step when using Docker.
These examples use faberNovel/docker-android and fastlane.
Use one version
- step:
type: Run
name: android version
identifier: android_version
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-30-v1.7.0
shell: Sh
command: |-
fastlane init
fastlane tests
Use multiple versions
- Add the matrix looping strategy configuration to your stage.
- stage:
strategy:
matrix:
androidVersion:
- 30
- 31
- 33
- Reference the matrix variable in the
image
field of your steps.
- step:
type: Run
name: android Version
identifier: android_version
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-<+ stage.matrix.androidVersion >-v1.7.0
shell: Sh
command: |-
fastlane init
fastlane tests
Deploy to the Google Play Store
The following examples use fastlane to deploy an app to the Google Play Store. These are intended as examples only. They do not provide complete firebase configuration or app distribution requirements. To learn more about app distribution, go to the Google documentation on Firebase App Distribution and the fastlane documentation on Deploying to Google Play using fastlane.
- Harness Cloud
- Self-hosted
- step:
type: Run
name: fastlane_deploy
identifier: fastlane_deploy
spec:
shell: Sh
command: |-
fastlane init
fastlane android deploy
fastlane action upload_to_play_store
- step:
type: Run
name: fastlane_deploy
identifier: fastlane_deploy
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-<+ stage.matrix.androidVersion >-v1.7.0
shell: Sh
command: |-
fastlane init
fastlane android deploy
fastlane action upload_to_play_store
Full pipeline examples
The following pipeline examples install dependencies, cache dependencies, and build and test an Android app.
- Harness Cloud
- Self-hosted
This pipeline uses Harness Cloud build infrastructure and Cache Intelligence.
If you copy this example, replace the placeholder values with appropriate values for your code repo connector, repository name, and other applicable values. Depending on your project and organization, you may also need to replace projectIdentifier
and orgIdentifier
.
pipeline:
name: default
identifier: default
projectIdentifier: default
orgIdentifier: default
properties:
ci:
codebase:
connectorRef: YOUR_CODE_REPO_CONNECTOR_ID
repoName: YOUR_REPO_NAME
build: <+input>
tags: {}
stages:
- stage:
name: build
identifier: build
description: ""
type: CI
spec:
cloneCodebase: true
caching:
enabled: true
paths:
- "YOUR_CACHE_PATH"
execution:
steps:
- step:
type: Run
identifier: dependencies
name: dependencies
spec:
shell: Sh
command: |-
bundle update
- step:
type: Run
name: Test
identifier: test
spec:
shell: Sh
command: |-
./gradlew test assemble -YOUR_PROJECT
./gradlew testDebug
reports:
type: JUnit
spec:
paths:
- "*/build/test-results/.*xml"
- step:
type: Run
name: fastlane_deploy
identifier: fastlane_deploy
spec:
shell: Sh
command: |-
fastlane init
fastlane android deploy
fastlane action upload_to_play_store
platform:
os: Linux
arch: Amd64
runtime:
type: Cloud
spec: {}
sharedPaths:
- YOUR_CACHE_PATH
This pipeline uses a Kubernetes cluster build infrastructure and Save and Restore Cache from S3 steps.
If you copy this example, replace the placeholder values with appropriate values for your code repo connector, repository name, and other applicable values. Depending on your project and organization, you may also need to replace projectIdentifier
and orgIdentifier
.
pipeline:
name: default
identifier: default
projectIdentifier: default
orgIdentifier: default
properties:
ci:
codebase:
connectorRef: YOUR_CODE_REPO_CONNECTOR_ID
repoName: YOUR_REPO_NAME
build: <+input>
tags: {}
stages:
- stage:
name: build
identifier: build
description: ""
type: CI
spec:
cloneCodebase: true
infrastructure:
type: KubernetesDirect
spec:
connectorRef: YOUR_KUBERNETES_CLUSTER_CONNECTOR_ID
namespace: YOUR_NAMESPACE
automountServiceAccountToken: true
nodeSelector: {}
os: Linux
execution:
steps:
steps:
- step:
type: RestoreCacheS3
name: Restore Cache From S3
identifier: Restore_Cache_From_S3
spec:
connectorRef: AWS_Connector
region: us-east-1
bucket: your-s3-bucket
key: cache-{{ checksum "package.json" }} ## Example cache key based on checksum.
archiveFormat: Tar
- step:
type: Run
identifier: dependencies
name: dependencies
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-30-v1.7.0
shell: Sh
command: |-
npm install -g firebase-tools
gem install fastlane
bundle exec fastlane add_plugin load_json
bundle exec fastlane add_plugin increment_version_code
bundle exec fastlane add_plugin firebase_app_distribution
- step:
type: Run
name: Test
identifier: test
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-30-v1.7.0
shell: Sh
command: |-
./gradlew test assemble -YOUR_PROJECT
./gradlew testDebug
reports:
type: JUnit
spec:
paths:
- "*/build/test-results/.*xml"
- step:
type: Run
name: fastlane_deploy
identifier: fastlane_deploy
spec:
connectorRef: account.harnessImage
image: fabernovel/android:api-<+ stage.matrix.androidVersion >-v1.7.0
shell: Sh
command: |-
fastlane init
fastlane android deploy
fastlane action upload_to_play_store
- step:
type: SaveCacheS3
name: Save Cache to S3
identifier: Save_Cache_to_S3
spec:
connectorRef: AWS_Connector
region: us-east-1
bucket: your-s3-bucket
key: cache-{{ checksum "package.json" }} ## Example cache key based on checksum.
sourcePaths:
- "YOUR_CACHE_PATH"
archiveFormat: Tar
Next steps
Now that you have created a pipeline that builds and tests an Android app, you could:
- Create triggers to automatically run your pipeline.
- Add steps to build and upload artifacts.
- Add a step to build and push an image to a Docker registry.
- Explore other ways to optimize and enhance CI pipelines.