Distribute Android apps to testers using Gradle

You can integrate App Distribution into your Android build process using the App Distribution Gradle plugin. The plugin lets you specify your testers and release notes in your app's Gradle file, letting you configure distributions for different build types and variants of your app.

This guide describes how to distribute Android App Bundles (AABs) to testers using the App Distribution Gradle plugin.

App Distribution integrates with Google Play’s internal app sharing service to process the AABs you upload and serve APKs that are optimized for your testers' device configurations. Distributing AABs lets you do the following:

  • Run optimized APKs (served by Google Play) that are optimized to your testers' devices.

  • Uncover and debug device-specific issues.

  • Test app bundle features like Play Feature Delivery and Play Asset Delivery.

  • Reduce the size of downloads for your testers.

Required permissions

To upload AABs to App Distribution, you must link your Firebase app to an app in Google Play. You must have the required level of access to perform these actions.

If you don't have the necessary Firebase access, you can ask a Firebase project Owner to assign you the applicable role via the Firebase console IAM settings. If you have questions about accessing your Firebase project, including finding or assigning an Owner, review the "Permissions and access to Firebase projects" FAQs.

The following table applies to linking a Firebase app to an app in Google Play, as well as uploading AABs.

Action in Firebase console Required IAM permission IAM role(s) that include required permissions by default Additional required role(s)
Link a Firebase app to an app in Google Play firebase.playLinks.update One of the following roles: Access to a Google Play developer account as Admin
Upload AABs to App Distribution firebaseappdistro.releases.update One of the following roles: ––

Before you begin

  1. If you haven't already, add Firebase to your Android project. At the end of this workflow, you'll have a Firebase Android App in your Firebase project.

    If you aren't using any other Firebase products, you only need to create a project and register your app. If you decide to use additional products, be sure to complete all of the steps in Add Firebase to your Android project.

  2. To create a Firebase link to Google Play and to upload AABs, make sure that your app meets the following requirements:

    • The app in Google Play and the Firebase Android app are both registered using the same package name.

    • The app in Google Play is set up on the app dashboard and is distributed to one of the Google Play tracks (Internal testing, Closed testing, Open testing, or Production).

    • The app's review in Google Play is complete and the app is published. Your app is published if the App status column displays one of the following statuses: Internal testing (not Draft internal testing), Closed testing, Open testing, or Production.

  3. Link your Firebase Android App to your Google Play developer account:

    1. In the Firebase console, go to your Project settings, then select the Integrations tab.

    2. On the Google Play card, click Link.
      If you already have links to Google Play, click Manage instead.

    3. Follow the on-screen instructions to enable the App Distribution integration and select which Firebase Android Apps to link to Google Play.

    Learn more about linking to Google Play.

Step 1. Set up your Android project

  1. In your root-level (project-level) Gradle file (<project>/build.gradle.kts or <project>/build.gradle), add the App Distribution Gradle plugin as a dependency:

    Kotlin

    plugins {
        // ...
        id("com.android.application") version "7.3.0" apply false
    
        // Make sure that you have the Google services Gradle plugin dependency
        id("com.google.gms.google-services") version "4.4.1" apply false
    
        // Add the dependency for the App Distribution Gradle plugin
        id("com.google.firebase.appdistribution") version "4.2.0" apply false
    }
    

    Groovy

    plugins {
        // ...
        id 'com.android.application' version '7.3.0' apply false
    
        // Make sure that you have the Google services Gradle plugin dependency
        id 'com.google.gms.google-services' version '4.4.1' apply false
    
        // Add the dependency for the App Distribution Gradle plugin
        id 'com.google.firebase.appdistribution' version '4.2.0' apply false
    }
    
  2. In your module (app-level) Gradle file (usually <project>/<app-module>/build.gradle.kts or <project>/<app-module>/build.gradle), add the App Distribution Gradle plugin:

    Kotlin

    plugins {
      id("com.android.application")
    
      // Make sure that you have the Google services Gradle plugin
      id("com.google.gms.google-services")
    
      // Add the App Distribution Gradle plugin
      id("com.google.firebase.appdistribution")
    }
    

    Groovy

    plugins {
      id 'com.android.application'
    
      // Make sure that you have the Google services Gradle plugin
      id 'com.google.gms.google-services'
    
      // Add the App Distribution Gradle plugin
      id 'com.google.firebase.appdistribution'
    }
    
  3. If you're behind a corporate proxy or firewall, add the following Java system property that enables App Distribution to upload your distributions to Firebase:

    -Djavax.net.ssl.trustStore=/path/to/truststore -Djavax.net.ssl.trustStorePassword=password
    

Step 2. Authenticate with Firebase

Before you can use the Gradle plugin, you must first authenticate with your Firebase project in one of the following ways. By default, the Gradle plugin looks for credentials from the Firebase CLI if no other authentication method is used.

Step 3. Configure your distribution properties

In your module (app-level) Gradle file (usually <project>/<app-module>/build.gradle.kts or <project>/<app-module>/build.gradle), configure App Distribution by adding at least one firebaseAppDistribution section.

For example, to distribute the release build to testers, follow these instructions::

Kotlin

import com.google.firebase.appdistribution.gradle.firebaseAppDistribution

android {

  // ...

  buildTypes {
      getByName("release") {
          firebaseAppDistribution {
              artifactType = "AAB"
              releaseNotesFile = "/path/to/releasenotes.txt"
              testers = "ali@example.com, bri@example.com, cal@example.com"
          }
      }
  }

  // ...
}

Groovy

android {

  // ...

  buildTypes {
      release {
          firebaseAppDistribution {
              artifactType="AAB"
              releaseNotesFile="/path/to/releasenotes.txt"
              testers="ali@example.com, bri@example.com, cal@example.com"
          }
      }
  }

  // ...
}

You can configure App Distribution for build types and product flavors.

For example, to distribute debug and release builds in "demo" and "full" product flavors, follow these instructions:

Kotlin

import com.google.firebase.appdistribution.gradle.firebaseAppDistribution

android {

  // ...

  buildTypes {
      getByName("debug") {...}
      getByName("release") {...}
  }

  flavorDimensions += "version"
  productFlavors {
      create("demo") {
          dimension = "version"
          firebaseAppDistribution {
              releaseNotes = "Release notes for demo version"
              testers = "demo@testers.com"
          }
      }
      create("full") {
          dimension = "version"
          firebaseAppDistribution {
              releaseNotes = "Release notes for full version"
              testers = "full@testers.com"
          }
      }
  }

  // ...
}

Groovy

android {

  // ...

  buildTypes {
      debug {...}
      release {...}
  }

  flavorDimensions "version"
  productFlavors {
      demo {
          dimension "version"
          firebaseAppDistribution {
              releaseNotes="Release notes for demo version"
              testers="demo@testers.com"
          }
      }
      full {
          dimension "version"
          firebaseAppDistribution {
              releaseNotes="Release notes for full version"
              testers="full@testers.com"
          }
      }
  }

  // ...
}

Use the following parameters to configure the distribution:

App Distribution Build Parameters
appId

Your app's Firebase App ID. Required only if you don't have the Google Services Gradle plugin installed. You can find the App ID in the google-services.json file or in the Firebase console on the General Settings page. The value in your build.gradle file overrides the value output from the google-services plugin.

appId="1:1234567890:android:321abc456def7890"
serviceCredentialsFile

The path to your service account private key JSON file. Required only if you use service account authentication.

artifactType

Specifies your app's file type. Can be set to "AAB" or "APK".

artifactPath

Absolute path to the APK or AAB file you want to upload.

releaseNotes or releaseNotesFile

Release notes for this build.

You can either specify the release notes directly or the path to a plain text file.

testers or testersFile

The email addresses of the testers you want to distribute builds to.

You can specify the testers as a comma-separated list of email addresses:

testers="ali@example.com, bri@example.com, cal@example.com"

Or, you can specify the path to a file containing a comma-separated list of email addresses:

testersFile="/path/to/testers.txt"
groups or groupsFile

The tester groups you want to distribute builds to (see Manage testers). Groups are specified using group aliases, which you can find in the Testers tab in the Firebase App Distribution console.

You can specify the groups as a comma-separated list of group aliases:

groups="qa-team, android-testers"

Or, you can specify the path to a file containing a comma-separated list of group aliases:

groupsFile="/path/to/tester-groups.txt"
testDevices or testDevicesFile

The following distribution types are part of the Automated tester beta feature.

The test devices you want to distribute builds to (see Automated tests).

You can specify the test devices as a semicolon-separated list of device specifications:

testDevices="model=shiba,version=34,locale=en,orientation=portrait;model=b0q,version=33,locale=en,orientation=portrait"

Or, you can specify the path to a file containing a semicolon-separated list of device specifications:

testDevicesFile="/path/to/testDevices.txt"
testUsername

The username for automatic login to be used during automated tests.

testPassword or testPasswordFile

The password for automatic login to be used during automated tests.

Or, you can specify the path to a plain text file containing a password:

testPasswordFile="/path/to/testPassword.txt"
testUsernameResource

Resource name for the username field for automatic login to be used during automated tests.

testPasswordResource

Resource name for the password field for automatic login to be used during automated tests.

testNonBlocking

Run automated tests asynchronously. Visit the Firebase console for the automatic test results.

stacktrace

Prints out the stacktrace for user exceptions. This is helpful when debugging issues.

Step 4. Distribute your app to testers

  1. Finally, to package your test app and invite testers, build the targets BUILD-VARIANT and appDistributionUploadBUILD-VARIANT with your project's Gradle wrapper, where BUILD-VARIANT is the optional product flavor and build type you configured in the previous step. For more information about product flavors, see Configure build variants.

    For example, to distribute your app using the release build variant, run the following command:

    ./gradlew bundleRelease appDistributionUploadRelease
    

    Or, if you authenticated with your Google Account and didn't provide credentials in your Gradle build file, include the FIREBASE_TOKEN variable:

    export FIREBASE_TOKEN=1/a1b2c3d4e5f67890
    ./gradlew --stop // Only needed for environment variable changes
    ./gradlew bundleRelease appDistributionUploadRelease
    
  2. You can also override the values set in your build.gradle file by passing command line arguments in the form of --<property-name>=<property-value>. For example:

    • To upload a debug build to App Distribution:

      ./gradlew bundleDebug appDistributionUploadDebug
          --artifactType="AAB"
      
    • To invite additional testers or remove existing testers from your Firebase project:

      ./gradlew appDistributionAddTesters
          --projectNumber=<project_number>
          --emails="anothertester@email.com, moretesters@email.com"
      ./gradlew appDistributionRemoveTesters
          --projectNumber=<project_number>
          --emails="anothertester@email.com, moretesters@email.com"
      

      Once a tester has been added to your Firebase project, you can add them to individual releases. Testers who are removed will no longer have access to releases in your project, but may still retain access to your releases for a window of time.

    You can also specify testers using --file="/path/to/testers.txt" instead of --emails.

    The appDistributionAddTesters and appDistributionRemoveTesters tasks also accept the following arguments:

    • projectNumber: Your Firebase project number.

    • serviceCredentialsFile: The path to your Google service credentials file. This is the same argument used by the upload action.

The Gradle plugin outputs the following links after the release upload. These links help you manage binaries and ensure that testers and other developers have the right release:

  • firebase_console_uri - A link to the Firebase console displaying a single release. You can share this link with other developers in your org.
  • testing_uri - A link to the release in the tester experience (Android native app) that lets testers view release notes and install the app onto their device. The tester needs access to the release in order to use the link.
  • binary_download_uri - A signed link that directly downloads and installs the app binary (APK or AAB file). The link expires after one hour.

Once you distribute your build, it becomes available in the App Distribution dashboard of the Firebase console for 150 days (five months). When the build is 30 days from expiring, an expiration notice appears in both the console and your tester's list of builds on their test device.

Testers who haven't been invited to test the app receive email invitations to get started, and existing testers receive email notifications that a new build is ready to test (read the tester set up guide for instructions on how to install the test app). You can monitor the status of each tester-whether they accepted the invitation and whether they downloaded the app-in the Firebase console.

Testers have 30 days to accept an invitation to test the app before it expires. When an invitation is 5 days from expiring, an expiration notice appears in the Firebase console next to the tester on a release. An invitation can be renewed by resending it using the drop-down menu on the tester row.

Next steps