Data types
Every type below is a public class exported from the package root
(lib/src/models.dart and lib/src/config.dart), so you can reference them
directly in your own function signatures and widget state:
import 'package:bgeo_background_geolocation/bgeo_background_geolocation.dart' as bg;
void onFix(bg.Location location) { ... }Fields declared non-nullable in the Dart source are always present on a
successfully-parsed object; fields declared with a trailing ? are
nullable/optional exactly as shown below — there is no separate “optional but
never actually null” convention here, unlike TypeScript’s ?:. Two classes
(Location, HeartbeatEvent, AuthorizationEvent) additionally expose a
raw field: the untouched native payload as a permissive Map<String, dynamic> escape hatch for fields not otherwise typed.
Location & sensors
Location
The core location record. It’s the payload of
onLocation and (when a fix
exists) the location field of
onMotionChange’s
MotionChangeEvent and
onHeartbeat’s
HeartbeatEvent; the resolved value of
getCurrentPosition(),
the onLocation callback of
watchPosition(),
setOdometer()/resetOdometer(),
and each element of
sync()/getLocations()’s
resolved list.
| Field | Type | Description |
|---|---|---|
uuid | String | Unique record id. |
timestamp | String | ISO-8601 UTC. |
age | double? | Optional. Fix age in milliseconds at the time it was processed. |
odometer | double | Cumulative odometer reading, metres. |
coords | Coords | Position/motion fields. |
activity | MotionActivity | Classified motion activity at the time of the fix. |
battery | Battery | Device battery snapshot. |
isMoving | bool? | Motion-state machine’s verdict at the time of this fix. null during a cold start’s unconfirmed-MOVING probing window (up to stopTimeout minutes after start()) — the engine emits is_moving: null there so a server falls back to speed rather than recording a phantom “started moving”. Treat null the same as false unless you care about the difference. |
sample | bool? | Optional. true when this Location was resolved by getCurrentPosition() — either an existing fix served for a fresh-enough maximumAge, or the best (most accurate) of several fixes sampled internally — rather than delivered by the ambient tracking stream. Also true on the fix resolved by setOdometer()/resetOdometer() — that fix carries event: 'odometer' (see below) rather than coming from getCurrentPosition(). |
event | String? | Optional. Tags why this record was produced when it isn’t a plain tracked fix. Observed values: 'motionchange' (the record captured just before entering the stationary state) and 'odometer' (the fix resolved by setOdometer()/resetOdometer()). |
extras | Map<String, dynamic>? | Optional passthrough — e.g. {'watch': true} on watchPosition() fixes. Config-level extras form the base of every record; per-call extras are layered on top. |
raw | Map<String, dynamic> | The untouched native payload (permissive escape hatch), keyed by the original snake_case wire field names. |
Field naming: unlike the RN/TS type (which keeps is_moving and some
coords/battery fields snake_case to mirror the wire format), every typed
Dart field here is camelCase (isMoving, altitudeAccuracy, isCharging,
…) — the snake_case → camelCase mapping happens internally in each class’s
fromMap constructor. Use raw if you need the original wire key names.
Coords
Nested inside Location.coords.
| Field | Type | Description |
|---|---|---|
latitude | double | Degrees. |
longitude | double | Degrees. |
accuracy | double | Horizontal accuracy, metres. |
altitude | double? | Optional. Metres above sea level. |
altitudeAccuracy | double? | Optional. Vertical accuracy, metres. |
speed | double? | Optional. Metres/second. |
speedAccuracy | double? | Optional. Metres/second. |
heading | double? | Optional. Degrees. |
headingAccuracy | double? | Optional. Degrees. |
ellipsoidalAltitude | double? | Optional. Metres, WGS84 ellipsoidal (as opposed to altitude, which is mean-sea-level/geoid-based). |
MotionActivity
Nested inside Location.activity. Its type values are also
the vocabulary accepted by
Config.triggerActivities
(a CSV of these same strings) — see the
activity type constants.
| Field | Type | Description |
|---|---|---|
type | String | Classified activity — one of 'still', 'on_foot', 'walking', 'running', 'on_bicycle', 'in_vehicle', 'unknown'. Not a Dart enum; a plain string matching the activityType* constants. |
confidence | int | Classifier confidence for type. |
Battery
Nested inside Location.battery.
| Field | Type | Description |
|---|---|---|
level | double | Battery level, 0.0–1.0. |
isCharging | bool | Whether the device is currently charging. |
State
The tracker’s state snapshot: resolved by
ready(),
setConfig(),
start(),
stop(), and
getState().
| Field | Type | Description |
|---|---|---|
enabled | bool | Whether tracking is enabled (the persisted on/off intent). |
isMoving | bool? | Optional. Current motion-state-machine verdict — same value as onMotionChange’s isMoving. |
odometer | double? | Optional. Cumulative odometer reading, metres. |
trackingMode | int? | Optional. Diagnostic. |
connected | bool? | Optional. Validated-internet connectivity — see ConnectivityChangeEvent. |
geofenceCount | int? | Optional. Diagnostic counter. |
raw | Map<String, dynamic> | The untouched native payload — every field the native engine returned, typed or not. |
Only a handful of fields are typed: unlike the RN State type (which
declares a larger superset of diagnostic fields such as lastRawFixAge,
locationFailureCount, backgroundRearmCount, monitoredWakeRegions, …),
the Dart State class only exposes the six fields above as typed properties.
Any other native-reported field is still reachable — State implements
operator [](String key) as a permissive index accessor, equivalent to
reading raw[key] directly:
final state = await bg.BackgroundGeolocation.getState();print(state.enabled);print(state['lastRawFixAge']); // untyped, dynamic — same map as state.rawEvents
ProviderChangeEvent
Payload of onProviderChange
and the resolved value of
getProviderState()
(same shape).
| Field | Type | Description |
|---|---|---|
status | int | One of the authorizationStatus* constants — 3 is Always. |
enabled | bool | Whether location services are on at all. |
gps | bool | GPS provider enabled. |
network | bool | Network provider enabled. |
accuracyAuthorization | int? | Optional, iOS only — accuracyAuthorizationFull/Reduced. |
MotionChangeEvent
Payload of onMotionChange.
| Field | Type | Description |
|---|---|---|
isMoving | bool | true on the moving transition, false on the stationary transition. |
location | Location? | Optional — null on the very first motionchange of a tracking session, before any fix exists yet (the initial probe fires ahead of any location). Guard before dereferencing — see the Events reference for the same caveat. |
HeartbeatEvent
Payload of onHeartbeat.
| Field | Type | Description |
|---|---|---|
location | Location? | Optional. The last known location — null if no fix has been taken yet in the current session. |
raw | Map<String, dynamic> | The untouched native payload. |
GeofenceEvent
Payload of onGeofence.
| Field | Type | Description |
|---|---|---|
identifier | String | The geofence’s identifier. |
action | String | The transition type — 'ENTER', 'EXIT', or 'DWELL'. Not a Dart enum. |
location | Location | The fix that triggered the transition. Required, not nullable. |
extras | Map<String, dynamic>? | Optional. The geofence’s own extras, echoed back. |
GeofencesChangeEvent
Payload of onGeofencesChange
— a delta of the OS-registered subset, not the full persisted set (see
Geofence below and the
Geofencing guide).
| Field | Type | Description |
|---|---|---|
on | List<Geofence> | Geofences newly registered with the OS. |
off | List<Geofence> | Geofences just unregistered. |
HttpEvent
Payload of onHttp — fired once
per completed location-sync HTTP request (log uploads do not emit this
event; see the logging guide).
| Field | Type | Description |
|---|---|---|
success | bool | true when status is 2xx. |
status | int | HTTP status code; 0 when the request never got a response (network error). |
responseText | String | Response body (or the error message when status is 0), truncated to 1024 characters. |
CrashEvent
Payload of onCrash — an
on-device collision confirmation. Armed only while moving, off by default;
see Config.crashDetection.
| Field | Type | Description |
|---|---|---|
timestamp | String | ISO-8601 UTC, the confirmation moment. |
peakG | double | Peak impact magnitude, in g. |
impactDurationMs | double | Duration of the impact signature, in ms. |
preImpactSpeedMps | double | Speed immediately before impact, in m/s. |
location | Location? | Last known fix at confirmation time, or null if none was available. |
DistractionEvent
Payload of onDistraction —
an on-device distracted-driving episode. Armed only while moving, off by
default; see
Config.distractionDetection.
This detects the phone being physically handled at driving speed — see
Limitations for what it cannot see.
| Field | Type | Description |
|---|---|---|
timestamp | String | ISO-8601, the moment the episode closed. |
startTimestamp | String | ISO-8601, the episode start (same instant as the dds extras key below). |
durationSec | double | Final episode duration in seconds (same value as the ddd extras key below). |
cause | String | "h" handling-only (iOS), "s" handling + active screen (Android), "c" reserved for calls (not implemented). |
location | Location? | Last known fix at close time, or null if none was available. |
Distraction extras keys
While an episode is open (and never lost to a sparse fix stream), the engine
stamps these keys into the extras of every uploaded Location — this is
the wire contract a backend parses, independent of the distraction event
above:
| Key | Type | When present | Meaning |
|---|---|---|---|
dds | number | On every uploaded fix while an episode is open, and on the closing fix. | Unix seconds of the episode start. This value doubles as the episode id. |
ddc | string | Alongside dds. | Cause: "h" handling-only (iOS), "s" handling + active screen (Android), "c" reserved for calls (not implemented). |
ddd | number | Only on the first fix persisted after the episode ends. | Final episode duration in seconds. |
Rules for a backend consuming these keys:
- Group fixes into an episode by equal
ddsvalue, not by adjacency in the fix stream — grouping by equal value survives gaps in delivery. - Episode duration is
dddfrom the closing fix. If the closing fix never arrives, fall back to the span of fixes carrying thatdds— this is only a lower bound. - A short episode can produce no fixes “inside” it. If an episode is
shorter than the interval between fixes, the next persisted fix simply
carries
dds,ddcanddddtogether. Episodes are therefore never lost to a sparse fix stream. - A pending close wins a race with a new open. If a new episode opens
before the previous episode’s close has been flushed to a fix, that fix
carries the pending close’s
dds/ddc/dddtriple in full; the newly opened episode’sdds/ddcpair is deferred to the next record. Grouping by equaldds(above) is unaffected either way. - Do not count episodes off the location stream. The closing triple
(
dds/ddc/ddd) rides every record built between the close and the first record that is actually persisted, so asample: trueone-shot and thelocationembedded inside another event can each carry it more than once. The uploaded-record contract is unaffected, but a consumer must count episodes from thedistractionevent instead — it fires once per episode in normal operation, but a rare disarm race can publish a seconddistractionevent for the same episode (samedds/startTimestamp, differentdurationSec/ddd). A consumer that needs exact counts should dedupe bystartTimestamp(equivalentlydds).
ConnectivityChangeEvent
Payload of onConnectivityChange.
Fired on validated-internet transitions (Android NET_CAPABILITY_VALIDATED /
iOS NWPath.satisfied — a captive-portal Wi-Fi network reports false); a
newly-registered listener also receives the current state as a synthetic
first delivery — see the
Events reference for
the exact semantics.
| Field | Type | Description |
|---|---|---|
connected | bool | Validated-internet reachability. |
AuthorizationEvent
Payload of onAuthorization
— the outcome of a native, killed-app-safe token refresh configured via
Config.authorization.
| Field | Type | Description |
|---|---|---|
success | bool | Whether the refresh succeeded. |
accessToken | String? | Present on success — the new access token. |
refreshToken | String? | Present on success — the new refresh token. |
status | int? | Present on failure — the HTTP status the refresh request itself received. |
raw | Map<String, dynamic> | The untouched native payload. |
Authorization state
AuthState
Resolved value of
getAuthState().
| Field | Type | Description |
|---|---|---|
accessToken | String? | Optional. The access token the native uploader currently holds. |
refreshToken | String? | Optional. The refresh token the native uploader currently holds. |
Geofencing
Geofence
A persisted geofence definition — the shape accepted by
addGeofence()/addGeofences()
and returned by
getGeofences() and the
on/off lists of GeofencesChangeEvent. See the
Geofencing guide for validation rules,
proximity slicing, and DWELL semantics.
| Field | Type | Description |
|---|---|---|
identifier | String | Unique geofence id. |
radius | double | Metres. |
latitude | double | Degrees. |
longitude | double | Degrees. |
notifyOnEntry | bool? | Optional. |
notifyOnExit | bool? | Optional. |
notifyOnDwell | bool? | Optional. |
loiteringDelay | int? | Optional. Milliseconds; required alongside notifyOnDwell for a DWELL transition. |
extras | Map<String, dynamic>? | Optional. Echoed back on the corresponding GeofenceEvent. |
Positioning options
CurrentPositionOptions
Parameter of getCurrentPosition().
| Field | Type | Description |
|---|---|---|
persist | bool? | Optional. Whether the resolved fix is added to the upload queue like a normal tracked point. |
samples | int? | Optional. Number of fixes to sample before returning the best (most accurate) one. |
timeout | int? | Optional. Seconds to wait before giving up. |
maximumAge | int? | Optional. Accept a cached fix up to this many milliseconds old instead of sampling a new one. |
desiredAccuracy | int? | Optional. One of the desiredAccuracy* constants. |
extras | Map<String, dynamic>? | Optional. Merged into the returned location’s extras. |
WatchPositionOptions
Parameter of watchPosition().
| Field | Type | Description |
|---|---|---|
interval | int? | Optional. Desired update interval, milliseconds. |
desiredAccuracy | int? | Optional. One of the desiredAccuracy* constants. |
persist | bool? | Optional. Whether fixes are added to the upload queue. |
extras | Map<String, dynamic>? | Optional. Merged into each returned location’s extras. |
Logging
LogEntry
Element type of the list resolved by
getLog(); written by
BackgroundGeolocation.logger’s
.error/.warn/.info/.debug/.verbose methods and the native engine
itself. See the logging guide for retention
and upload cadence.
| Field | Type | Description |
|---|---|---|
ts | String | ISO-8601 UTC. |
level | int | 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG, 5=VERBOSE. |
src | String | 'native' or 'js' (app-side Dart logger.* calls are tagged 'js' for RN/Transistor wire-format parity). |
event | String | Short event tag. |
message | String? | Optional. Human-readable log line. |
data | dynamic | Optional. JSON-decoded data attached to the line. |
Headless
HeadlessEvent
Parameter of the HeadlessTask passed to
registerHeadlessTask()
— Android only.
typedef HeadlessTask = Future<void> Function(HeadlessEvent event);| Field | Type | Description |
|---|---|---|
name | String | The event type — one of 'heartbeat', 'motionchange', 'geofence', 'providerchange', 'powersavechange', 'http', 'connectivitychange'. 'location' is deliberately not part of this set — see below. |
params | Map<String, dynamic> | The rest of the event’s fields — e.g. a headless motionchange carries isMoving/location inside params, distinct from name. |
No headless location: the Android engine never dispatches a location
event headlessly. High-frequency location fixes are deliberately excluded to
avoid spinning up a background isolate (and a wakelock) per fix while
tracking, which would drain battery and risk ANRs/foreground-service-start
restrictions; fixes taken while the Dart isolate isn’t running are still
durably queued and uploaded natively. This mirrors the same note under
onLocation on the Events
reference. iOS never invokes a registered headless task at all — see
registerHeadlessTask().
Configuration value classes
These two immutable classes are nested inside
Config — pass instances of them as the
notification and authorization named parameters.
Notification
Value of Config.notification
Android — configures the persistent
foreground-service notification required for background location. No-op on
iOS, which has no equivalent concept.
| Field | Type | Description |
|---|---|---|
title | String? | Optional. |
text | String? | Optional. |
channelId | String? | Optional. Android freezes channel importance per channelId — change the id to change importance. |
channelName | String? | Optional. |
smallIcon | String? | Optional. "drawable/name" or "mipmap/name". |
color | String? | Optional. "#RRGGBB". |
priority | int? | Optional. Transistor NOTIFICATION_PRIORITY_* scale: -2 MIN (default) .. 2 MAX. |
Authorization
Value of Config.authorization
— native token refresh so killed-app uploads survive an access-token expiry
without a live Dart context. On a 401/403 the uploader exchanges
refreshToken at refreshUrl (with refreshHeaders, body refreshPayload
— the literal placeholder "{refreshToken}" is substituted; defaults to
{refresh_token}). Outcomes surface via
onAuthorization.
| Field | Type | Description |
|---|---|---|
strategy | String? | Optional. |
accessToken | String? | Optional. |
refreshToken | String? | Optional. |
refreshUrl | String? | Optional. |
refreshPayload | Map<String, dynamic>? | Optional. Body template; "{refreshToken}" is substituted with the current refresh token. |
refreshHeaders | Map<String, String>? | Optional. |
Subscriptions
Every on* listener method returns a plain Dart
StreamSubscription<T>
rather than a custom type — see the
Events reference for
the full model, including
removeListeners() to
tear down every listener at once.