PersistenceConfig¶
classPersistenceConfig
Persistence and storage configuration for the background geolocation SDK.
PersistenceConfig controls how the SDK stores, orders, templates, and purges
records in its on-device SQLite database — the durable buffer between data
producers (locations, geofences) and consumers (your app and the HTTP service).
Contents¶
Overview¶
The SDK maintains an internal SQLite database as a rolling queue. Each recorded LocationEvent and geofence event is written immediately, then consumed and deleted by downstream services. The SDK prefers an empty database — records exist only while awaiting upload or retrieval.
| Category | Properties | Notes |
|---|---|---|
| Retention | maxDaysToPersist, maxRecordsToPersist |
TTL and count-based purge limits. |
| Ordering | locationsOrderDirection |
Controls upload and retrieval order. |
| Templates | locationTemplate, geofenceTemplate |
Custom JSON structure for uploads. |
| Extras | extras |
Static key/value pairs merged into every record. |
| Persist mode | persistMode |
Which event types are written to SQLite. |
| Diagnostics | disableProviderChangeRecord |
Suppress provider-change records. |
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.maxDaysToPersist = 3
persistence.maxRecordsToPersist = 1000
persistence.extras = mapOf(
"user_id" to 123,
"appVersion" to "1.2.3"
)
persistence.persistMode = PersistMode.ALL
}
Storage lifecycle¶
Records are written to SQLite immediately upon recording and deleted when any of the following occur:
- Your server returns a
20xresponse for the HTTP upload (see HttpConfig) - You call BGGeo.destroyLocations
maxDaysToPersistelapses (rolling TTL purge)maxRecordsToPersistwould be exceeded (oldest records are dropped)
Inspect the pending queue with BGGeo.getCount or BGGeo.getLocations.
Ordering¶
locationsOrderDirection controls the order in which records are selected
for upload or returned by BGGeo.getLocations:
"ASC"— oldest first (default)"DESC"— newest first
Templates¶
By default the SDK serializes locations and geofence events using its standard
JSON schema. Use locationTemplate and geofenceTemplate to
substitute a custom ERB template that reshapes the JSON to match your backend.
Use extras to merge static key/value metadata into every record at write
time, without a custom template.
Persist mode¶
persistMode controls which event types are written to SQLite. All events
are still delivered to their live callbacks (BGGeo.onLocation,
BGGeo.onGeofence) regardless of this setting. Events that
are not persisted are not eligible for HTTP uploads via HttpConfig.url.
The persist option on individual API calls can override this setting per-request:
// Within a coroutine scope
val bgGeo = BGGeo.instance
val location = bgGeo.getCurrentPosition(
persist = true,
extras = mapOf("get_current_position" to true),
samples = 3
)
Examples¶
Now grouped under PersistenceConfig¶
val bgGeo = BGGeo.instance
bgGeo.config.edit {
persistence.maxDaysToPersist = 14
persistence.maxRecordsToPersist = 5000
persistence.locationsOrderDirection = LocationsOrderDirection.ASC
persistence.locationTemplate = "{...}"
persistence.geofenceTemplate = "{...}"
persistence.persistMode = PersistMode.ALL
persistence.extras = mapOf("user_id" to 123)
persistence.disableProviderChangeRecord = true
}
Configure persistence behavior¶
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.maxDaysToPersist = 14
persistence.maxRecordsToPersist = 5000
persistence.locationsOrderDirection = LocationsOrderDirection.ASC
persistence.persistMode = PersistMode.ALL
persistence.extras = mapOf("user_id" to 123, "appVersion" to "1.2.3")
http.url = "https://example.com/locations"
http.autoSync = true
}
Inspect and purge the database¶
val bgGeo = BGGeo.instance
val pending = bgGeo.store.count
Log.d(TAG, "Pending records: $pending")
// Purge all records
bgGeo.store.destroyAll()
Log.d(TAG, "Destroyed all records")
Custom JSON templates¶
val bgGeo = BGGeo.instance
bgGeo.config.edit {
persistence.locationTemplate = """
{
"lat": <%= latitude %>,
"lng": <%= longitude %>,
"ts": "<%= timestamp %>",
"meta": <%= JSON.stringify(extras) %>
}
""".trimIndent()
persistence.geofenceTemplate = """
{
"id": "<%= identifier %>",
"action": "<%= action %>",
"ts": "<%= timestamp %>"
}
""".trimIndent()
}
Members¶
disableProviderChangeRecord¶
Android only Disables the automatic insertion of a synthetic "provider-change" location into the SDK's SQLite database and its subsequent HTTP upload.
By default, when an BGGeo.onProviderChange event fires, the Android SDK records a special location documenting when and where the device's location-services state changed (e.g., GPS disabled). This behavior historically existed to support platforms with limited or unreliable Headless Task implementations (e.g., Cordova, Capacitor).
Set this to true if your server-side JSON schema or locationTemplate
cannot accommodate the automatically injected provider field.

// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.disableProviderChangeRecord = true
}
extras¶
Optional arbitrary key/value pairs merged into each recorded location at write time.
These values are persisted and included in all HTTP uploads, making them
ideal for attaching static contextual metadata such as user_id, route_id,
or session_id.
See also
- HTTP Guide
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
http.url = "https://my-server.com/locations"
http.params = mapOf("device_id" to "abc123")
persistence.extras = mapOf("route_id" to 1234)
}
The resulting HTTP request body:
POST /locations
{
"device_id": "abc123",
"location": {
"coords": {
"latitude": 45.51927004945047,
"longitude": -73.61650072045029
},
"extras": {
"route_id": 1234
}
}
}
geofenceTemplate¶
Optional custom ERB template for reshaping GeofenceEvent JSON in HTTP uploads.
Behaves like locationTemplate but includes two additional tags:
geofence.identifier and geofence.action. Use Ruby-style ERB tags to
interpolate field values:
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.geofenceTemplate =
"""{"lat":<%= latitude %>, "lng":<%= longitude %>, "geofence":"<%= geofence.identifier %>:<%= geofence.action %>"}"""
}
// Or a compact Array form:
bgGeo.config.edit {
persistence.geofenceTemplate =
"""[<%= latitude %>, <%= longitude %>, "<%= geofence.identifier %>", "<%= geofence.action %>"]"""
}
Warning
The SDK does not automatically apply double-quotes around string data. Templates are JSON-encoded exactly as written.
Produces invalid JSON:
Template tags¶
Identical to locationTemplate with the following additions:
| Tag | Type | Description |
|---|---|---|
geofence.identifier |
String |
Identifier of the activated geofence |
geofence.action |
String |
"ENTER" or "EXIT" |
latitude |
Float |
|
longitude |
Float |
|
speed |
Float |
Meters |
heading |
Float |
Degrees |
accuracy |
Float |
Meters |
altitude |
Float |
Meters |
altitude_accuracy |
Float |
Meters |
timestamp |
String |
ISO-8601 |
uuid |
String |
Unique ID |
event |
String |
motionchange, geofence, heartbeat, providerchange |
odometer |
Float |
Meters |
activity.type |
String |
still, on_foot, running, on_bicycle, in_vehicle, unknown |
activity.confidence |
Integer |
0–100% |
battery.level |
Float |
0–100% |
battery.is_charging |
Boolean |
Whether device is plugged in |
mock |
Boolean |
True when location was generated from a mock app |
is_moving |
Boolean |
True if recorded while in moving state |
timestampMeta |
Object |
Timestamp metadata; see GeolocationConfig.enableTimestampMeta |
See also
- locationTemplate
- HttpConfig.rootProperty
- HTTP Guide
Incorrect¶
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.geofenceTemplate = """{"timestamp": <%= timestamp %>}"""
}
Correct¶
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.geofenceTemplate = """{"timestamp": "<%= timestamp %>"}"""
}
locationTemplate¶
Optional custom ERB template for reshaping LocationEvent JSON in HTTP uploads.
When set, the SDK evaluates the template string against each location record before serializing it. Use Ruby-style ERB tags to interpolate field values:
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.locationTemplate =
"""{"lat":<%= latitude %>,"lng":<%= longitude %>,"event":"<%= event %>",isMoving:<%= is_moving %>}"""
}
// Or use a compact Array template:
bgGeo.config.edit {
persistence.locationTemplate =
"""[<%=latitude%>, <%=longitude%>, "<%=event%>", <%=is_moving%>]"""
}
Warning
The SDK does not automatically insert quotes around string values. Templates are JSON-encoded exactly as written.
The following produces invalid JSON because timestamp is a string but is
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.locationTemplate = """{"timestamp": <%= timestamp %>}"""
}
This renders invalid JSON:
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
persistence.locationTemplate = """{"timestamp": "<%= timestamp %>"}"""
}
Configured extras¶
If extras are configured, the key/value pairs are merged directly
into the rendered location JSON.
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
http.url = "https://my.server.com/locations"
http.rootProperty = "data"
persistence.locationTemplate = """{"lat":<%= latitude %>,"lng":<%= longitude %>}"""
persistence.extras = mapOf("foo" to "bar")
}
Produces:
Template tags¶
| Tag | Type | Description |
|---|---|---|
latitude |
Float |
|
longitude |
Float |
|
speed |
Float |
Meters |
heading |
Float |
Degrees |
accuracy |
Float |
Meters |
altitude |
Float |
Meters |
altitude_accuracy |
Float |
Meters |
timestamp |
String |
ISO-8601 |
uuid |
String |
Unique ID |
event |
String |
motionchange, geofence, heartbeat, providerchange |
odometer |
Float |
Meters |
activity.type |
String |
still, on_foot, running, on_bicycle, in_vehicle, unknown |
activity.confidence |
Integer |
0–100% |
battery.level |
Float |
0–100% |
battery.is_charging |
Boolean |
Is device plugged in? |
mock |
Boolean |
True if generated by mock provider |
is_moving |
Boolean |
Device was moving when recorded |
timestampMeta |
Object |
Timestamp metadata; see GeolocationConfig.enableTimestampMeta |
See also
- HTTP Guide
- geofenceTemplate
- HttpConfig.rootProperty
locationsOrderDirection¶
var locationsOrderDirection:LocationsOrderDirection
Sort order used when selecting records for upload or returning them from
BGGeo.getLocations. Defaults to "ASC" (oldest first).
"ASC"— oldest records first"DESC"— newest records first
maxDaysToPersist¶
Maximum number of days to retain a persisted record in the SDK's on-device
SQLite database. Defaults to 1 day.
When your server fails to return a 20x response, the SDK continues retrying
uploads. If a record remains unuploaded for longer than maxDaysToPersist days,
it is permanently discarded to prevent unbounded database growth.
maxRecordsToPersist¶
Maximum number of records the SDK may retain in its on-device SQLite database.
Defaults to -1 (no limit).
When a limit is set and the stored record count would exceed it, the oldest records are purged to make room for the newest.
See HttpEvent for details on upload behavior.
persistMode¶
var persistMode:PersistMode
Controls which event types the SDK writes to its internal SQLite database. Defaults to PersistMode.All.
All recorded events are always delivered to their live callbacks (BGGeo.onLocation and BGGeo.onGeofence). This setting only determines what is written to persistent storage. Events that are not persisted are also not eligible for HTTP uploads via HttpConfig.url.
| Value | Description |
|---|---|
| PersistMode.All | Default — persist both location and geofence events. |
| PersistMode.Location | Persist location events only. |
| PersistMode.Geofence | Persist geofence events only. |
| PersistMode.None | Persist nothing. |
Warning
This setting is intended for specialized cases. For example, if you need
continuous location tracking via BGGeo.start but only
want to store geofence events, configure persistMode: PersistMode.Geofence.