Firebase App Distribution Integration in Mobile Applications
Firebase App Distribution is not an alternative to TestFlight, it's a complement. TestFlight is limited to 90-day build lifetime and requires Apple review for each external tester. App Distribution distributes .ipa and .apk to testers directly, without store, in minutes. For teams with daily builds — critically important.
What Usually Goes Wrong During Integration
Most common mistake is skipping GoogleService-Info.plist or google-services.json step. App Distribution is a Firebase service, and SDK initializes via FirebaseApp.configure(). If plist is added only to main target and not included in test target's membership — crash on startup when checking for updates.
Second common scenario: iOS app builds via ad-hoc profile for testing, but tester's UDID not added to profile — device just won't install .ipa. App Distribution automatically collects UDIDs, but adding them to provisioning profile is developer responsibility. Solved via fastlane match with automatic profile updates.
Integration via Fastlane
Working scheme with fastlane:
lane :distribute_firebase do
# Build
build_ios_app(
scheme: "MyApp",
configuration: "Release",
export_method: "ad-hoc"
)
# Upload to Firebase App Distribution
firebase_app_distribution(
app: "1:123456789:ios:abcdef",
groups: "qa-team, beta-users",
release_notes: last_git_commit[:message],
firebase_cli_token: ENV["FIREBASE_TOKEN"]
)
end
firebase_cli_token is token from firebase login:ci. Stored in CI/CD secret variables (GitHub Actions secrets, GitLab CI variables), not in repository.
groups are tester groups created in Firebase Console. Groups allow differentiating access: QA team gets all builds, beta users — only stable ones.
Automatic Tester Notifications
App Distribution SDK can show native alert on startup if new version available. For iOS:
import FirebaseAppDistribution
// AppDelegate.application(_:didFinishLaunchingWithOptions:)
AppDistribution.appDistribution().checkForUpdate { release, error in
guard let release = release else { return }
// Show alert with release.displayVersion and release.releaseNotes
let alert = UIAlertController(
title: "Update available \(release.displayVersion)",
message: release.releaseNotes ?? "",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "Update", style: .default) { _ in
UIApplication.shared.open(release.downloadURL)
})
}
Important: checkForUpdate works only for testers authorized in Firebase. In production build this code must not exist — #if DEBUG or separate build flag.
Android: Same Pattern
FirebaseAppDistribution.getInstance().updateIfNewReleaseAvailable()
.addOnProgressListener { updateProgress ->
// Update progress bar
}
.addOnFailureListener { e ->
if (e is FirebaseAppDistributionException) {
when (e.errorCode) {
FirebaseAppDistributionException.Status.NOT_IMPLEMENTED ->
// SDK not in test environment — production build
}
}
}
CI/CD Integration Without Fastlane
Via Firebase CLI directly:
firebase appdistribution:distribute app-release.apk \
--app $FIREBASE_APP_ID \
--groups "qa-team" \
--release-notes "$(git log -1 --pretty=%B)" \
--token $FIREBASE_TOKEN
Step added in GitHub Actions workflow after build step. Upload time for 50 MB .ipa — about 90 seconds.
Timeline
Firebase App Distribution integration into existing CI/CD (iOS + Android): 2–4 days. Tester groups setup, auto-update checks in app, Fastlane integration: 1–1.5 weeks. Cost estimated individually.







