Android
You can build and test Android applications using a Linux or Mac platform on Harness Cloud, a self-managed Kubernetes cluster, or a local runner build infrastructure.
This guide assumes you've created a Harness CI pipeline.
Specify architecture
- Harness Cloud
- Self-managed
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-managed 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-managed 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-managed
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: YOUR_IMAGE_REGISTRY_CONNECTOR
      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.
- Cache Intelligence
- Save and Restore Cache steps
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 (as well as additional build tools). 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
You can use built-in steps to:
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 Test 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 CI also supports test splitting (parallelism) for both Run and Test steps.
- Harness Cloud
- Self-managed
- 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: YOUR_IMAGE_REGISTRY_CONNECTOR
      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: YOUR_IMAGE_REGISTRY_CONNECTOR
      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-managed
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: YOUR_IMAGE_REGISTRY_CONNECTOR
      image: fabernovel/android:api-30-v1.7.0
      shell: Sh
      command: |-
        fastlane init
        fastlane testsUse multiple versions
- stage:
    strategy:
      matrix:
        androidVersion:
          - 30
          - 31
          - 33
image field of your steps.- step:
    type: Run
    name: android Version
    identifier: android_version
    spec:
      connectorRef: YOUR_IMAGE_REGISTRY_CONNECTOR
      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: YOUR_IMAGE_REGISTRY_CONNECTOR
      image: fabernovel/android:api-30-v1.7.0
      shell: Sh
      command: |-
        fastlane init
        fastlane testsUse multiple versions
- stage:
    strategy:
      matrix:
        androidVersion:
          - 30
          - 31
          - 33
image field of your steps.- step:
    type: Run
    name: android Version
    identifier: android_version
    spec:
      connectorRef: YOUR_IMAGE_REGISTRY_CONNECTOR
      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-managed
- 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: YOUR_IMAGE_REGISTRY_CONNECTOR
      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-managed
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: YOUR_IMAGE_REGISTRY_CONNECTOR
                    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: YOUR_IMAGE_REGISTRY_CONNECTOR
                    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: YOUR_IMAGE_REGISTRY_CONNECTOR
                    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.