Skip to content

Limitations

We’d rather you know the gaps up front than discover them after buying.

Not implemented yet

  • No Flutter web/desktop support. iOS & Android only — the closed-source native engine is mobile-only, so there is no web, macOS, Windows, or Linux implementation, and none is planned. See Compatibility.
  • A larger set of Transistorsoft config/methods is deliberately out of scope, not a temporary gap — see Migration: API parity for the full list (schedule, templates, getLocations() pagination/SQL, startBackgroundTask, getDeviceInfo, and others).

Accepted-but-no-op config keys

These are accepted for API compatibility but currently do nothing:

KeyStatus
foregroundServiceNo-op — the Android foreground service required for background location is always on while tracking, regardless of this key. No equivalent concept on iOS.
backgroundPermissionRationaleNo-op on iOS; Android uses its own permission-rationale flow (shouldShowRequestPermissionRationale) instead of a config-driven dialog.
debugNot a no-op, but plays audible sound cues only (location, heartbeat, motion-change, stop-timeout, geofence events) — it does not affect tracking, filtering, or upload behavior.

The Config reference flags foregroundService and backgroundPermissionRationale inline with a “No-op” badge.

Platform-specific config keys

These keys are fully functional on their home platform and a silent no-op on the other:

KeyHome platformNo-op on
stationaryLocationUpdateIntervalAndroidiOS
activityRecognitionIntervalAndroidiOS
locationUpdateIntervalAndroidiOS
showsBackgroundLocationIndicatoriOSAndroid
stationaryDistanceFilteriOSAndroid
preventSuspendiOSAndroid
useSessionEngineiOS (17+; the value is stored but unread on Android)Android

Platform notes

  • Geofence transitions fire past the boundary — that is OS behavior, not a bug. Both platforms deliberately debounce region crossings to avoid flapping on GPS noise. On iOS, Core Location reports ENTER/EXIT only after the device has cleared the radius plus a system-defined cushion: an EXIT typically arrives tens of seconds after the geometric crossing — at running or driving speed that is roughly 100–300 m beyond the circle, and in the worst case minutes later. On Android, transitions add up to ~30 s of reporting latency (notificationResponsiveness) on top of fused-location detection lag. The location attached to a geofence event is the last accepted fix at the moment the OS delivered the transition, so on a map the event marker lands where the device was when the OS made its decision, not on the circle’s edge. This applies to anything built on the platform geofencing services — see the Geofencing guide. If your use case needs tighter boundaries, compare distance to the fence center in your own onLocation handler while tracking is active.
  • Offline queue persistence. The offline upload queue is stored in SQLite (bgeo.db, location_events table) with maxRecordsToPersist/ maxDaysToPersist retention; geofences persist in the same database. Persisted native log rows have their own retention — logMaxDays plus a hard 25,000-row cap.
  • iOS background delivery is subject to Core Location’s rules. BGeo uses a session-based engine (CLLocationUpdate.liveUpdates + CLBackgroundActivitySession, on by default on iOS 17+ via useSessionEngine) plus a wake region so tracking resumes after kill/eviction/reboot, but exact cadence depends on iOS, device settings (Low Power Mode, Background App Refresh, Precise Location), and OS scheduling. iOS < 17 always uses the legacy delivery path regardless of this flag.
  • registerHeadlessTask() is Android-only. iOS relaunches the app natively on a significant-location-change wake instead of running a headless dispatcher — there is no AppRegistry-equivalent headless execution path on iOS. registerHeadlessTask() retains your task on iOS but never invokes it while the app process isn’t running; native uploads, retries, and token refresh continue regardless. See Boot & killed-app behavior. On Android, headless dispatch deliberately excludes raw location events (only heartbeat, motionchange, geofence, providerchange, powersavechange, http, and connectivitychange reach a headless task) — see the same guide’s Android headless tasks section. The HeadlessTask you pass must be a top-level function or a static method — a closure or instance method can’t be resolved by PluginUtilities.getCallbackHandle in a fresh background isolate, and registerHeadlessTask() throws an ArgumentError immediately (before any platform call) if you pass one.
  • Android OEM battery managers can force-stop apps and drop geofence/activity-recognition/boot callbacks until the app is reopened. A battery-optimization exemption is the only reliable mitigation on such devices — this affects every background-location SDK.