Skip to content

Configuration

BeekonConfig has three arms: Local (app-owned config, no upload), Custom (app-owned config + your own backend via a required sync), and Cloud (server-owned config via a project key — see Beekon Cloud). The Local and Custom arms both carry the same TrackingConfig; this page is the single, authoritative reference for its fields. The Quickstart shows the minimal set; everything else is here.

App-owned tracking is built around two scalars — a minimum time interval and a minimum distance between emitted fixes. They form an AND-gate: a position is emitted only when both pass.

(now - lastAdmittedTime >= intervalSeconds) AND
(distance(lastAdmittedFix) >= distanceMeters)

The first fix after start() always passes. Set either field to 0 to disable that side of the gate. That’s the entire signal-processing surface in v1 — no Kalman filter, no outlier rejection, no speed clamp. The OS provider (FusedLocationProviderClient / Core Location) is the source of truth; Beekon forwards it faithfully.

TrackingConfig carries exactly six knobs — the tracking gate and nothing else:

FieldTypeDefaultNotes
minTimeBetweenLocationsSecondsLong / Int / int / number30Min seconds between kept fixes. 0 disables the time gate.
minDistanceBetweenLocationsMetersDouble / Double / double / number100Min metres between kept fixes. 0 disables the distance gate; AND-ed with time.
accuracyModeAccuracyModebalancedBattery-vs-accuracy preset — see enums.
whenStationaryStationaryModepauseWhat to do while the device is still — see enums.
stationaryRadiusMetersDouble / Double / double / number5Radius of the internal stationary geofence. Clamped to 5…1000.
detectActivityBoolean / Bool / bool / booleanfalseClassify physical motion onto each fix. Needs a second OS permission — see Locations & history.

Type columns read Android / iOS / Flutter / React Native.

Everything that isn’t a tracking knob lives on the BeekonConfig arm, not on TrackingConfig:

FieldOn armsDefaultNotes
trackingCustom, Localall defaultsThe TrackingConfig above. In Cloud mode the server owns these knobs.
syncCustom (required)Your upload config — see Sync & your backend. Local never uploads; Cloud derives its own endpoints.
notificationall armsForeground-service notification. Android only. See below.
licenseKeyCustom, LocalnullSigned license token — see Licensing. Cloud delivers the license from the server.
logLevelall armsinfoDiagnostic log threshold — see Diagnostics.

Cloud is built by a validating factory — it throws/errors at configure time rather than failing later on the network:

  • The project key is cell-aware: bkproj_<cell>_<secret> (the cell names the Beekon Cloud region your project lives in, e.g. in1). With no explicit endpoint, the SDK derives https://api.<cell>.getbeekon.com from the key — zero network calls, no global fallback host.
  • Typed rejections: an empty key is key_empty; a key without a parseable cell and no explicit endpoint is key_missing_cell; an explicit endpoint must be a clean https base URL (no query, no fragment).
  • An explicit endpoint (self-hosted Beekon) always overrides derivation.
// Android — throws BeekonException.InvalidConfiguration on a bad key/endpoint
Beekon.configure(
BeekonConfig.cloud(
projectKey = "bkproj_in1_...",
notification = notification,
),
)
// iOS — throws on a bad key/endpoint
try await Beekon.shared.configure(
BeekonConfig.cloud(projectKey: "bkproj_in1_...")
)

In cloud mode the tracking knobs arrive from the server as a remote config document — sectioned (tracking / sync / privacy / features / diagnostics), cached on-device, applied whole-document with fresh > cache > defaults precedence. Tracking never blocks on configuration: a device that can’t reach the server runs its last-good config, or compiled defaults if it has never connected.

The SDK is the final authority on battery safety. Every remote knob passes a device-enforced clamp table (floors and ceilings baked into the SDK) before it is applied — no server value, including a compromised one, can push the device outside safe ranges, redirect uploads, or change the auth recipe. The full knob inventory and clamp bounds are normative in the cloud-mode spec.

AccuracyMode — battery vs. accuracy:

ValueAndroidiOS / FlutterReact NativeBehaviour
HighAccuracyMode.High.high / AccuracyMode.high'high'Most accurate fixes, highest battery cost
Balanced (default)AccuracyMode.Balanced.balanced / AccuracyMode.balanced'balanced'City-block accuracy at moderate cost
LowAccuracyMode.Low.low / AccuracyMode.low'low'Coarse, low-power fixes; distance gate floored to 500 m

StationaryMode — behaviour while the device is still:

ValueAndroidiOS / FlutterReact NativeBehaviour
Keep trackingStationaryMode.KeepTracking.keepTracking / StationaryMode.keepTracking'keepTracking'Keep admitting fixes even while stationary. Highest battery cost.
Pause (default)StationaryMode.Pause.pause / StationaryMode.pause'pause'Stop admitting fixes while stationary; resume silently on movement.
Pause with check-insStationaryMode.PauseWithCheckIns.pauseWithCheckIns / StationaryMode.pauseWithCheckIns'pauseWithCheckIns'Stop while stationary, but record a check-in fix roughly every 15 minutes.

Android requires a visible foreground-service notification while location is captured in the background. Set it via BeekonConfig.notification — it’s ignored on iOS. This is the persistent service notification that keeps the background process alive; it’s distinct from the per-crossing geofence notifications, which fire on enter/exit on every platform.

FieldTypeDefaultNotes
titlestring"Tracking location"Notification title.
textstringnullNotification body. null shows the title only.
smallIconstringnullStatus-bar icon — an Android drawable/mipmap resource name. null falls back to the launcher icon.

Call configure(...) again at any time — including while tracking — to update the gate. New values take effect on the next admitted fix without restarting the underlying location subscription.

// Tighten cadence mid-session
Beekon.configure(
BeekonConfig.Local(
tracking = TrackingConfig(
minTimeBetweenLocationsSeconds = 5,
minDistanceBetweenLocationsMeters = 25.0,
accuracyMode = AccuracyMode.High,
whenStationary = StationaryMode.Pause,
),
notification = notification,
),
)

The defaults (30 s / 100 m, balanced, pause) are a good general-purpose starting point. Adjust per scenario:

ScenariointervalSecondsdistanceMetersaccuracyModeNotes
Passive background (“where did I go?”)60150lowCoarse trail; cheaper on battery
General tracking (default)30100balancedDriving, cycling, multi-hour walks
Active foreground (turn-by-turn, fitness)5102550highUsers feel the battery hit in background
Stationary monitoring (geofence-like)0100balancedEmit only on movement, not on cadence

These are starting points, not presets — calibrate against your own data.