Notify testers about new builds

The optional Firebase App Distribution iOS and Android SDKs let you display in-app alerts to your testers when new builds of your app are available to install. This guide explains how to use the App Distribution iOS and Android SDKs to create and customize new build alerts for your testers.

Before you begin

If you haven't already, add Firebase to your Android project.

Step 1: Enable the App Distribution Tester API

  1. Select your project in the Google Cloud console.

  2. Under Firebase App Testers API, click Enable.

Step 2: Add App Distribution to your app

The App Distribution Android SDK consists of two libraries:

  • firebase-appdistribution-api - The API-only library, which you can include in all build variants.
  • firebase-appdistribution - The full SDK implementation (optional).

The API-only library lets your code make calls to the SDK. The calls will have no effect if the full SDK implementation is not present.

Declare the dependency for the App Distribution Android SDK in your module (app-level) Gradle file (usually <project>/<app-module>/build.gradle.kts or <project>/<app-module>/build.gradle). To avoid including the full SDK implementation's self-update functionality in your Play builds, add the API-only library dependency to all build variants. Only add the full SDK implementation to variants that are intended exclusively for pre-release testing.

dependencies {
    // ADD the API-only library to all variants
    implementation("com.google.firebase:firebase-appdistribution-api:16.0.0-beta12")

    // ADD the full SDK implementation to the "beta" variant only (example)
    betaImplementation("com.google.firebase:firebase-appdistribution:16.0.0-beta12")
}

Looking for a Kotlin-specific library module? Starting with the October 2023 release, both Kotlin and Java developers can depend on the main library module (for details, see the FAQ about this initiative).

Step 3: Configure in-app alerts

The App Distribution Android SDK provides provides the following ways to set up in-app build alerts for your testers:

  • A basic alert configuration that comes with pre-built app update and sign-in dialogs to display to testers.
  • An advanced alert configuration that allows you to customize your own user interface.

If you're using the App Distribution Android SDK for the first time, we recommend using the Basic Configuration.

Basic configuration

Use updateIfNewReleaseAvailable to display a pre-built enable alerts dialog to testers who haven't yet enabled alerts, and then check if a new build is available. When called, the method enacts the following sequence:

  1. Checks if a tester has enabled alerts. If the tester has not yet enabled alerts, the method prompts the tester to sign in to App Distribution with their Google account.

  2. Checks for newly available builds for the tester to install.

  3. Displays a pre-built alert prompting the tester to update.

  4. If the new build is an Android App Bundle (AAB), redirects the tester to Google Play to complete the update process.

    If the new build is an Android application PacKage (APK), the SDK downloads the new build in the background and prompts the tester to install when the download completes. The SDK sends download progress notifications to the user using NotificationManager. You can also add your own progress indicator by attaching an onProgressUpdate handler to the updateIfNewReleaseAvailable Task.

You can call updateIfNewReleaseAvailable at any point in your app. For example, you can call updateIfNewReleaseAvailable during the onResume method of the app's main activity.

The following example checks if the tester enabled alerts and has access to a new build. If these conditions are met, a dialog is displayed when the build is available to install:

Kotlin+KTX

// Copy and paste this into any part of your app - for example, in your main
// activity's onResume method.
val firebaseAppDistribution = FirebaseAppDistribution.getInstance()
firebaseAppDistribution.updateIfNewReleaseAvailable()
    .addOnProgressListener { updateProgress ->
      // (Optional) Implement custom progress updates in addition to
      // automatic NotificationManager updates.
    }
    .addOnFailureListener { e ->
      // (Optional) Handle errors.
      if (e is FirebaseAppDistributionException) {
        when (e.errorCode) {
          Status.NOT_IMPLEMENTED -> {
            // SDK did nothing. This is expected when building for Play.
          }
          else -> {
            // Handle other errors.
          }
        }
      }
    }

Java

// Copy and paste this into any part of your app - for example, in your main
// activity's onResume method.
FirebaseAppDistribution firebaseAppDistribution = FirebaseAppDistribution.getInstance();
firebaseAppDistribution.updateIfNewReleaseAvailable()
    .addOnProgressListener(updateProgress -> {
      // (Optional) Implement custom progress updates in addition to
      // automatic NotificationManager updates.
    })
    .addOnFailureListener(e -> {
      // (Optional) Handle errors.
      if (e instanceof FirebaseAppDistributionException) {
        switch (((FirebaseAppDistributionException)e).getErrorCode()) {
          case NOT_IMPLEMENTED:
            // SDK did nothing. This is expected when building for Play.
            break;
          default:
            // Handle other errors.
            break;
        }
      }
    });

Advanced configuration

Advanced sign-in configuration

The methods signInTester and isTesterSignedIn give you more flexibility to customize your tester's sign-in experience, so that the tester experience can better match your app's look and feel.

The following example checks whether the tester has already signed into their App Distribution tester account. This lets you choose to display your sign-in user interface (UI) only to testers who haven't yet signed in. After the tester signs in, you can then call updateIfNewReleaseAvailable to check whether the tester has access to a new build.

Kotlin+KTX

// Only show sign-in UI if this is the "beta" variant (example).
if (BuildConfig.BUILD_TYPE == "beta" && !firebaseAppDistribution.isTesterSignedIn) {
    // Start your sign-in UI here.
}

// Only check for updates if the tester is already signed in (do not prompt).
if (firebaseAppDistribution.isTesterSignedIn) {
    firebaseAppDistribution.updateIfNewReleaseAvailable().addOnFailureListener {
        // Handle failed update.
    }
}

Java

// Only show sign-in UI if this is the "beta" variant (example).
if (BuildConfig.BUILD_TYPE == "beta" && !firebaseAppDistribution.isTesterSignedIn()) {
    // Start your sign-in UI here.
}

// Only check for updates if the tester is already signed in (do not prompt).
if (firebaseAppDistribution.isTesterSignedIn()) {
    firebaseAppDistribution.updateIfNewReleaseAvailable().addOnFailureListener( e -> {
        // Handle failed update.
    });
}

From your sign-in UI, when the tester chooses to proceed, call signInTester():

Kotlin+KTX

firebaseAppDistribution.signInTester().addOnSuccessListener {
  // Handle successful sign-in.
}.addOnFailureListener {
  // Handle failed sign-in.
});

Java

firebaseAppDistribution.signInTester().addOnSuccessListener( unused -> {
  // Handle successful sign-in.
}).addOnFailureListener(e -> {
  // Handle failed sign-in.
});

Advanced update configuration

The methods checkForNewRelease and updateApp give you more flexibility to customize when your tester is prompted to update. You can also customize the pre-built update dialog and download progress indicator so they can better match your app's look and feel.

Note that updateApp doesn't provide download progress indication. This means that you need to implement your own progress indication using NotificationManager, some kind of in-app status display, or some other approach.

The following example checks whether a new release is available and then displays a custom UI. Before calling checkForNewRelease and updateApp, make sure that the tester is signed in by using the advanced sign-in configuration.

Kotlin+KTX

firebaseAppDistribution.checkForNewRelease().addOnSuccessListener { release ->
    if (release != null) {
        // New release available. Start your update UI here.
    }
}.addOnFailureListener {
    // Handle failed check for new release. Fails with Status#NOT_IMPLEMENTED
    // if built for Play.
}

Java

firebaseAppDistribution.checkForNewRelease().addOnSuccessListener(release -> {
    if (release != null) {
        // New release available. Start your update UI here.
    }
}).addOnFailureListener(e -> {
    // Handle failed check for new release. Fails with Status#NOT_IMPLEMENTED
    // if built for Play.
});

When the tester chooses to proceed with the update from your update UI, call updateApp():

Kotlin+KTX

firebaseAppDistribution.updateApp()
    .addOnProgressListener { updateState ->
      // Use updateState to show update progress.
    }

Java

firebaseAppDistribution.updateApp()
    .addOnProgressListener(updateState -> {
      // Use updateState to show update progress.
    });

Step 4: Build and test your implementation

Build your app and test your implementation by distributing the build to testers using the Firebase console.

Visit the App Distribution Troubleshooting guide for help with common issues, such as:

  • Tester not receiving in-app alerts
  • Tester being prompted to sign in to Google more than once