@ajuarezso/capacitor-background-geolocation-firestore
v0.1.3
Published
Capacitor plugin that combines background geolocation with native Firestore writes. The foreground service writes location updates directly to Firestore from native code (Java/Swift) using the Firebase Admin SDK, bypassing the JS bridge. This solves the A
Downloads
587
Maintainers
Readme
@ajuarezso/capacitor-background-geolocation-firestore
Capacitor plugin that combines background geolocation with native Firestore writes. The foreground service writes location updates directly to Firestore from native code (Java/Swift), bypassing the JS bridge — so location tracking keeps working even when the Capacitor WebView is suspended in Android 14+ background mode.
Why this plugin exists
Standard Capacitor background-geolocation plugins (@capgo/background-geolocation, @capacitor-community/background-geolocation) all deliver location callbacks through the JS bridge. On Android 14+, when the app goes to background, the WebView suspends JS execution — the native service keeps running and queues callbacks, but they don't reach JS until the WebView resumes. The result: a delivery driver's app shows no location updates for the customer until the driver re-opens the app.
The only existing solution is @transistorsoft/capacitor-background-geolocation — commercial, ~$300/year. This plugin is the free open-source equivalent: it writes location updates directly from Java/Swift to Firestore using the Firebase SDK, without going through the JS bridge.
Status
✅ v0.1.0 feature-complete — pending physical device validation.
| Component | Status | |---|---| | TypeScript API + definitions | ✅ Done | | Web fallback (browser dev) | ✅ Done | | Package scaffold (npm/rollup/tsconfig) | ✅ Done | | Android native (Java + Firebase Firestore SDK) | ✅ Done (Plugin + Service + FirestoreWriter, validated via gradle assemble) | | iOS native (Swift + FirebaseFirestore framework) | ✅ Done (Plugin + Service + FirestoreWriter, code complete) | | Plugin↔Service wiring | ✅ Done (static singleton + 100/200/400ms retry-backoff) | | Authentication / ID token refresh | ✅ Done (delegated to Firebase Auth SDK native — auto-refresh) | | Headless mode (survives WebView suspension) | ✅ Done (native writes don't depend on JS bridge) | | README ES | ✅ Done | | CHANGELOG | ✅ Done | | MIGRATION guide (from Capgo) | ✅ Done | | Architecture doc | ✅ Done | | Troubleshooting guide | ✅ Done | | Examples (Angular delivery driver) | ✅ Done | | Unit tests (Java + Swift, 12 each) | ✅ Done | | CI workflow | ✅ Done | | Offline queue (SQLite Android / JSON iOS) | ✅ Done | | Physical device validation | 🚧 Pending | | npm publish | 🚧 Pending (token expired, regenerate to publish) |
API
import { BackgroundGeolocationFirestore } from '@ajuarezso/capacitor-background-geolocation-firestore';
// 1. Start the watcher
await BackgroundGeolocationFirestore.start({
backgroundTitle: 'My App — Delivery in progress',
backgroundMessage: 'Sharing location with the customer',
distanceFilter: 5, // Android: 5m to avoid FusedLocation rate limit
requestPermissions: true,
}, (location, error) => {
if (location) console.log('Foreground tick:', location);
});
// 2. Configure native Firestore writes — bypasses JS bridge
await BackgroundGeolocationFirestore.setFirestoreContext({
docPath: 'drivers/abc123',
locationField: 'currentLocation',
projectId: 'my-firebase-project',
idToken: await user.getIdToken(),
writeThresholdMeters: 20,
});
// 3. Refresh the ID token every ~50 minutes (tokens expire at 60min)
setInterval(async () => {
await BackgroundGeolocationFirestore.setFirestoreContext({
...options,
idToken: await user.getIdToken(true),
});
}, 50 * 60 * 1000);
// 4. When done
await BackgroundGeolocationFirestore.clearFirestoreContext();
await BackgroundGeolocationFirestore.stop();How it works (planned implementation)
Android
- Foreground service with
android:foregroundServiceType="location"(inherited from base plugin) LocationCallback.onLocationResulttriggers on every fix- Distance throttle in Java (default 20m write threshold)
- Firebase Firestore Android SDK (
com.google.firebase:firebase-firestore) writes the doc using the stored ID token notifyListeners("firestoreWrite", ...)emits to JS for diagnostics — but the write succeeds regardless of JS state
iOS
- Background location authorization (Always)
CLLocationManagerDelegate.locationManager(_:didUpdateLocations:)triggers on every fix- Same throttle + Firebase Firestore iOS SDK pattern
ID Token refresh
The JS layer must call setFirestoreContext again before the current token expires (Firebase Auth tokens last 1 hour). The plugin doesn't auto-refresh — that's the consumer's responsibility, because token refresh requires the Firebase Auth SDK which is JS-side.
Roadmap
- [ ] Physical device validation (Android 14+ background suspension scenario, iOS Always-authorization flow)
- [ ] Publish to npm (token regeneration pending)
- [ ] Geofencing native events (entered/exited zone) — fired from Java/Swift without JS bridge
- [ ] Motion activity detection (still/walking/driving) to adapt
distanceFilterdynamically - [ ] Integration test app (Capacitor sample driving the full lifecycle)
- [ ] Battery telemetry diagnostics
License
MIT © Anthony Juarez Solis
