Files
crowd-funder-for-time-pwa/doc/android-firebase-gms.md

67 lines
3.9 KiB
Markdown

# Android — Firebase, Google Play Services, and FOSS Distribution
## Overview
The app is designed to work on Android devices with and without Google Play Services (GMS). Firebase/FCM push notifications are an opt-in feature at build time; all other functionality works on GMS-less devices (F-Droid, LineageOS without OpenGApps, etc.).
## How the opt-in guard works
`android/app/build.gradle` applies the `com.google.gms.google-services` Gradle plugin only when **both** conditions are true:
1. `android/google-services.json` is present on disk
2. The Gradle property `firebaseEnabled` is explicitly passed
```groovy
if (servicesJSON.exists() && servicesJSON.text && project.hasProperty('firebaseEnabled')) {
apply plugin: 'com.google.gms.google-services'
}
```
This means the file can live on disk for development purposes without accidentally activating Firebase.
## Build commands
| Target | Command | Firebase |
|---|---|---|
| APK / sideload / Zapstore | `./gradlew assembleRelease` | off |
| Aurora / Play Store without FCM | `./gradlew bundleRelease` | off |
| Play Store with FCM push notifications | `./gradlew bundleRelease -PfirebaseEnabled` | on |
| F-Droid | `./gradlew assembleRelease` | off (required) |
## Behavior on non-GMS devices
When built with `-PfirebaseEnabled`, Firebase SDKs check for GMS availability at startup and degrade gracefully if it is absent:
- Firebase initializes but detects no GMS
- FCM skips token registration silently (no token, no notifications)
- The app continues to work normally
This means a single Play Store AAB (`bundleRelease -PfirebaseEnabled`) covers both GMS and non-GMS users. GMS users get push notifications; non-GMS users get a fully functional app without them.
**Aurora Store** pulls the exact APK from Play Store servers, so Aurora users get whichever variant was uploaded. The Play Store AAB built with `-PfirebaseEnabled` is correct for Aurora.
**F-Droid** is stricter: their build policy rejects any APK with GMS dependencies at the binary level, even with graceful degradation. F-Droid submission would require a separate `assembleRelease` build (no flag) and a dedicated F-Droid listing.
## The `google-services.json` file
- Gitignored (`android/.gitignore` line 80) — never commit it
- Contains Firebase project credentials (project number, app ID, API key)
- Safe to leave on disk; has no effect unless `-PfirebaseEnabled` is passed
- Obtain from the Firebase console: Project Settings → Your apps → Android app → Download `google-services.json`
## Known GMS dependency: MLKit barcode scanner
`@capacitor-mlkit/barcode-scanning` unconditionally depends on `com.google.android.gms:play-services-code-scanner` (present since the plugin was first added at v6.0.0). This merges `com.google.android.gms.version` and `GoogleApiActivity` into the APK manifest regardless of the `-PfirebaseEnabled` flag.
Practical impact:
- **GMS devices**: barcode scanning works normally
- **Non-GMS devices**: barcode scanning fails at scan time (not at startup); the app launches and runs normally otherwise
This is an accepted trade-off. Removing it would require either forking the plugin or introducing a `foss` product flavor that excludes the MLKit plugin entirely — work to undertake if/when F-Droid submission is planned.
## Incident: June 2026
Jose Olarte III's `notify-api` branch placed a production `google-services.json` in `android/` to test Firebase Cloud Messaging. The branch was never merged to `master`, but because the file is gitignored it persisted on disk after switching branches. At the time, the Gradle conditional activated Firebase based on file presence alone (no opt-in flag), so all subsequent local builds embedded Firebase and required Google Play Services. This silently broke APK/Aurora/Zapstore distribution.
**Fix applied:** deleted `google-services.json` from disk, changed the Gradle conditional to require `-PfirebaseEnabled`, and documented the rule in `AGENTS.md`.