Skip to content

Background execution

Background tracking is the most divergent area between platforms. The state machine, gate, and schema are uniform — but the OS mechanics that keep your app alive differ fundamentally. Beekon picks the right mechanism per platform; you just need to understand what it’s doing so you can debug when it doesn’t.

Beekon runs a foreground service typed FOREGROUND_SERVICE_LOCATION (Android 14+) backed by FusedLocationProviderClient. The service holds a partial wake lock for the duration of tracking.

MechanismRole
FusedLocationProviderClientthe location source — fuses GPS, Wi-Fi, cell, sensor signals
Foreground service + notificationsatisfies Android 8+ background-location rules; visible to user
FOREGROUND_SERVICE_LOCATION typerequired for Android 14+ to start a location FGS
SharedPreferences (in.wayq.beekon)persists tracking intent so a host-driven cold launch can resume

The foreground notification is required by the platform, not a Beekon design choice. The notification channel id and notification id are SDK-internal constants; the title, body, and status-bar icon are configurable via NotificationConfig — see Configuration.

Android 15+ blocks BOOT_COMPLETED from launching foreground services, and Android has no equivalent to iOS’s Significant Location Change wake. If you want background tracking to survive process death, call Beekon.start() (or resumeIfNeeded() on the wrappers) from your Application.onCreate — the SDK rehydrates the last BeekonConfig and re-arms the gate.

Aggressive OEM battery managers can kill foreground services on devices from Xiaomi, Huawei, Samsung, OPPO, Vivo, and others. The dontkillmyapp.com matrix maps OEM-specific workarounds (auto-start whitelisting, battery-optimisation exemption). Surface those user-facing instructions in your app’s onboarding for affected devices. When the service is killed entirely, Beekon transitions state to Stopped(System); your app calls start() again when appropriate.

Android’s Doze mode (device idle) and App Standby (per-app idle) reduce wake-up frequency for backgrounded apps. The foreground service exempts you from most of this, but not all — expect coarser update cadence during deep doze. Beekon’s gate means you simply emit fewer fixes during these periods rather than dropping mid-trip.

iOS background execution is fundamentally about whether your app is alive at all. Beekon’s iOS 17+ stack is a single code path:

CLLocationUpdate.liveUpdates(.default)
+ CLBackgroundActivitySession // keeps background delivery alive
+ CLServiceSession(authorization: .always) // iOS 18+ only, declared-authorization

CLLocationUpdate.liveUpdates is the async sequence Apple introduced to replace the delegate; CLBackgroundActivitySession is what makes it survive backgrounding. The configuration is fixed at CLLocationUpdate.LiveConfiguration.default — power-profile tuning isn’t exposed publicly. Rate is governed by Beekon’s interval + distance gate.

Beekon runs a Significant Location Change monitor alongside liveUpdates. SLC is the only mechanism that wakes a terminated iOS app from coarse movement; liveUpdates does not.

When SLC wakes your app into a fresh process, the host app drives resume:

  1. Call await Beekon.shared.start() early in your App init.
  2. Beekon reads the persisted tracking intent from a UserDefaults suite (in.wayq.beekon); if none is saved it falls back to the all-defaults BeekonConfig.selfManaged().
  3. The fresh process has a new state stream — re-subscribe; the latest state replays.

Force-quit by the user permanently disables SLC until the next foreground open — that’s an Apple platform behaviour, not something Beekon controls.

You need Always authorization for background tracking. iOS forces a two-step prompt: WhenInUse first, then Always after the user has used the relevant feature once. Asking for Always straight away is silently denied. Beekon does not drive these prompts — the host app does. See Platform setup.

For end-to-end background validation, the sample apps are the canonical test rigs: beekon-android/sample (Compose) and beekon-ios/Sample (SwiftUI). A real-device 30–60 minute walk with the app backgrounded is the only way to truly verify background reliability — emulators and simulators lie about doze/SLC.