make a fix for running in an emulator, plus doc changes
This commit is contained in:
@@ -13,7 +13,7 @@ This guard is in `android/app/build.gradle`. Do NOT change this conditional to a
|
||||
|
||||
`google-services.json` is intentionally excluded from git (`android/.gitignore`). Never commit it.
|
||||
|
||||
Full details, incident history, and F-Droid notes: `doc/development/android-firebase-gms.md`
|
||||
Full details, incident history, and F-Droid notes: `doc/android-firebase-gms.md`
|
||||
|
||||
## Android Build — MLKit Barcode Scanner
|
||||
|
||||
|
||||
+5
-9
@@ -1329,6 +1329,7 @@ npm run build:android:prod # Production build (builds for production e
|
||||
# Auto-run builds
|
||||
npm run build:android:test:run # Test build with auto-run (builds then runs on emulator)
|
||||
npm run build:android:prod:run # Production build with auto-run (builds then runs on emulator)
|
||||
# Auto-run targets the one connected device; with none or several it prompts, or exits 9 without a terminal
|
||||
|
||||
# Debug and release builds
|
||||
npm run build:android:debug # Debug build (builds debug APK)
|
||||
@@ -1454,20 +1455,15 @@ npx cap open android
|
||||
|
||||
#### Android Build from the console
|
||||
|
||||
```bash
|
||||
cd android
|
||||
./gradlew clean
|
||||
./gradlew build -Dlint.baselines.continue=true
|
||||
cd -
|
||||
```
|
||||
* Note that this currently fails: `./gradlew build -Dlint.baselines.continue=true`
|
||||
|
||||
... or, to create the `aab` file, `bundle` instead of `build` (but not signed and not usable in Play Store):
|
||||
To create the `aab` file, `bundle` instead of `build` (but not signed and not usable in Play Store):
|
||||
|
||||
```bash
|
||||
./gradlew bundleDebug -Dlint.baselines.continue=true
|
||||
```
|
||||
|
||||
... or, to create a signed `aab` release:
|
||||
So, to create a signed `aab` release:
|
||||
|
||||
- Setup by adding the app/gradle.properties.secrets file (see properties at top
|
||||
of app/build.gradle) and the app/time-safari-upload-key-pkcs12.jks file
|
||||
@@ -1843,7 +1839,7 @@ npm run build:android:assets
|
||||
- Configure signing keys
|
||||
- Check device/emulator setup
|
||||
|
||||
## Additional Resources
|
||||
## Additional Documentation
|
||||
|
||||
- [Electron Build Patterns](doc/electron-build-patterns.md)
|
||||
- [iOS Build Scripts](doc/ios-build-scripts.md)
|
||||
|
||||
@@ -42,6 +42,16 @@ This means a single Play Store AAB (`bundleRelease -PfirebaseEnabled`) covers bo
|
||||
|
||||
**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.
|
||||
|
||||
## Push registration in builds without Firebase
|
||||
|
||||
A build without `-PfirebaseEnabled` contains the `@capacitor/push-notifications` plugin, but no Firebase config. In that build, `PushNotifications.register()` throws `Default FirebaseApp is not initialized` on the Capacitor plugin thread, which kills the app; a JS `try/catch` cannot intercept it.
|
||||
|
||||
The JS therefore asks native code first. `NotificationInspector.isFirebaseConfigured()` (`android/app/src/main/java/app/timesafari/notifications/NotificationInspectorPlugin.java`) reports whether the `google_app_id` string resource exists; the google-services Gradle plugin generates that resource only when Firebase is enabled, and it is the same signal Firebase's auto-initialization uses. `firebaseMessagingClient.ts` skips `register()` on Android when it is absent (or when the check fails), logging `No Firebase config in this Android build; skipping push registration`. Listener setup and the notification permission request run either way, since local daily notifications need that permission.
|
||||
|
||||
`NotificationInspector` must be listed in `scripts/restore-local-plugins.js`: `MainActivity` registers plugins after the Capacitor bridge is built, so a plugin missing from `capacitor.plugins.json` reports "not implemented on android" and the check falls back to skipping push.
|
||||
|
||||
Any code that calls `PushNotifications.register()` or other `FirebaseMessaging` APIs on Android must go through the same check.
|
||||
|
||||
## The `google-services.json` file
|
||||
|
||||
- Gitignored (`android/.gitignore` line 80) — never commit it
|
||||
@@ -64,3 +74,9 @@ This is an accepted trade-off. Removing it would require either forking the plug
|
||||
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`.
|
||||
|
||||
## Incident: September 2026
|
||||
|
||||
After the June fix, local builds without `-PfirebaseEnabled` (including every `scripts/build-android.sh` build and the FOSS APKs from v1.4.4 on) crashed at launch as soon as notification permission was granted, because startup code called `PushNotifications.register()` unconditionally. Found while running `npm run build:android:prod:run` on an emulator.
|
||||
|
||||
**Fix applied:** the `isFirebaseConfigured()` gate described in "Push registration in builds without Firebase", plus adding `NotificationInspector` to `scripts/restore-local-plugins.js` so the check is reachable on Android.
|
||||
|
||||
@@ -658,7 +658,18 @@ fi
|
||||
# we already synced and ran restore-local-plugins.js above, so skip sync here.
|
||||
if [ "$AUTO_RUN" = true ]; then
|
||||
log_step "Auto-running Android app..."
|
||||
safe_execute "Launching app" "npx cap run android --no-sync" || {
|
||||
# With exactly one connected device, target it directly. Otherwise cap run
|
||||
# shows an interactive picker, which without a terminal exits 0 having
|
||||
# launched nothing, so fail instead of reporting a false success.
|
||||
run_devices=$(adb devices | awk 'NR > 1 && $2 == "device" { print $1 }')
|
||||
run_target=""
|
||||
if [ "$(printf '%s\n' "$run_devices" | grep -c .)" = "1" ]; then
|
||||
run_target="--target $run_devices"
|
||||
elif [ ! -t 0 ]; then
|
||||
log_error "Auto-run needs exactly one connected device when not run from a terminal (found: ${run_devices:-none})"
|
||||
exit 9
|
||||
fi
|
||||
safe_execute "Launching app" "npx cap run android --no-sync $run_target" || {
|
||||
log_error "Failed to launch Android app"
|
||||
log_info "You can manually run with: npx cap run android --no-sync"
|
||||
exit 9
|
||||
|
||||
Reference in New Issue
Block a user