Methods
Everything hangs off the BackgroundGeolocation object. Methods that talk to
the engine are suspend — call them from a coroutine, not from a callback
soup.
All methods at a glance
| Method | Returns | Notes |
|---|---|---|
attach(context) | Unit | Mandatory, in Application.onCreate |
ready(config) | State | Configure; does not start tracking |
setConfig(config) | State | Change config on a running engine |
start() | State | Begin tracking; persists |
stop() | State | Stop tracking |
getState() | State | Snapshot + health fields |
changePace(isMoving) | Unit | Force the motion state |
getCurrentPosition(options) | Location | One-shot fix |
watchPosition(options) | Unit | High-frequency stream |
stopWatchPosition() | Unit | |
requestPermission(requester) | AuthorizationStatus | Staged escalation |
getProviderState() | ProviderState | Grant + provider availability |
isPowerSaveMode() | Boolean | |
getOdometer() | Double | Metres |
setOdometer(value) | Location | |
resetOdometer() | Location | setOdometer(0.0) |
addGeofence(geofence) | Unit | |
addGeofences(list) | Unit | |
removeGeofence(identifier) | Unit | |
removeGeofences() | Unit | All of them |
getGeofences() | List<Geofence> | |
geofenceExists(identifier) | Boolean | |
sync() | List<Location> | Flush the queue now |
getCount() | Int | Records pending |
getLocations() | List<Location> | Read the queue |
destroyLocations() | Int | Empty the queue |
destroyLocation(uuid) | Unit | Drop one record |
insertLocation(json) | Unit | Inject a record |
getAuthState() | AuthState | Current token pair |
getLog(limit) | List<LogEntry> | |
destroyLog() | Int | |
uploadLog() | Int | |
logger.info(...) etc. | Unit | Write your own lines |
onX(handler) | Subscription | See Events |
removeListeners() | Unit | Detach every callback |
The geofence, queue and logger methods are extension functions — Android
Studio will offer the import, but they are com.bgeo.sdk.addGeofence,
com.bgeo.sdk.sync and so on rather than members of the object.
Lifecycle
attach()
class MyApplication : Application() { override fun onCreate() { super.onCreate() BackgroundGeolocation.attach(this) }}Wires the engine to the process and resumes tracking if it was enabled before
the process died. Mandatory, once, in Application.onCreate — see
Installation for why nowhere
else will do.
It also attaches the event hub. Events the engine emitted before any subscriber
existed are buffered (up to 64 per event name) and replayed to the first
subscriber, so a cold start does not lose its launch-time providerchange.
ready()
val state = BackgroundGeolocation.ready(Config(distanceFilter = 10.0))Applies configuration and brings the engine up. Does not start tracking —
state.enabled tells you whether tracking is already running from a previous
process, which is the normal case after a reboot.
Throws BGeoException.License* in a release build with a bad key. The config is
applied before the licence is checked, so a licence failure still leaves your
configuration in place.
setConfig()
BackgroundGeolocation.setConfig(Config(distanceFilter = 50.0))Changes configuration on a running engine — power keys (distanceFilter,
disableElasticity, locationUpdateInterval) take effect on the live location
request without a stop/start cycle.
Only the keys you set are changed; Config’s null defaults are omitted from
the patch rather than sent as nulls.
start()
BackgroundGeolocation.start()BackgroundGeolocation.stop()stop()
start() checks the licence first, then persists the intent — tracking
survives backgrounding, process death and reboot until stop(). stop() never
consults the licence: an expired key can never trap a user in a tracking state
they cannot turn off.
getState()
val state = BackgroundGeolocation.getState()state.enabled // typedstate["lastAcceptedFixAge"] as? Double // health fields, from rawSee State for the fields the
Android engine reports.
changePace()
BackgroundGeolocation.changePace(true)Forces the motion state machine into moving or stationary — the manual
override for “I know a trip just started”. Throws BGeoException.Disabled
when tracking is off, rather than silently doing nothing.
Geolocation
getCurrentPosition()
val location = BackgroundGeolocation.getCurrentPosition( CurrentPositionOptions(samples = 3, timeout = 30.0, persist = false),)One-shot fix, independent of start(): it works while tracking is off and does
not turn tracking on. samples collects several fixes and returns the most
accurate; persist = false keeps it out of the upload queue.
Throws on timeout or permission failure.
watchPosition()
BackgroundGeolocation.watchPosition(WatchPositionOptions(interval = 1.0))stopWatchPosition()
BackgroundGeolocation.stopWatchPosition()A high-frequency stream for a foreground map. There is no separate channel:
fixes arrive through the ordinary
locations stream.
Failures arrive as locationerror
events, not exceptions — including “called on an unlicensed build”. Without a
subscriber there, a failing watch fails silently. It also drains battery fast;
stop it when the screen you opened it for goes away.
Permissions & providers
requestPermission()
val status = BackgroundGeolocation.requestPermission(permissionRequester)Runs the staged escalation described in
Permissions and returns the final
AuthorizationStatus.
getProviderState()
val provider = BackgroundGeolocation.getProviderState()if (!provider.enabled) { /* location services are off device-wide */ }isPowerSaveMode()
if (BackgroundGeolocation.isPowerSaveMode()) { /* expect a sparser track */ }Odometer
getOdometer()
setOdometer()
resetOdometer()
val metres = BackgroundGeolocation.getOdometer()BackgroundGeolocation.setOdometer(0.0)BackgroundGeolocation.resetOdometer() // the same thing, namedThe odometer accumulates across sessions and process deaths; it only moves for
fixes that pass the filter (and, if odometerAccuracyThreshold is set, an
extra accuracy gate). setOdometer returns the fix it used to re-anchor.
Geofences
addGeofence()
addGeofences()
removeGeofence()
removeGeofences()
getGeofences()
geofenceExists()
BackgroundGeolocation.addGeofence( Geofence( identifier = "home", latitude = 52.52, longitude = 13.405, radius = 200.0, notifyOnEntry = true, notifyOnExit = true, ),)BackgroundGeolocation.addGeofences(listOf(/* … */))BackgroundGeolocation.removeGeofence("home")BackgroundGeolocation.removeGeofences()val fences = BackgroundGeolocation.getGeofences()val exists = BackgroundGeolocation.geofenceExists("home")Geofences persist across process death in the engine’s own database — add them
once, not on every launch. Adding an identifier that already exists replaces
it. An invalid definition (no identifier, non-positive radius, bad coordinates)
throws BGeoException.InvalidGeofence.
Android limits how many regions an app may monitor; the engine keeps the
nearest maxMonitoredGeofences armed and swaps as you move, reporting each
swap through
geofenceschange. Every
fence you added still exists regardless of what is currently armed.
See Geofencing.
Upload queue
sync()
getCount()
getLocations()
destroyLocation()
destroyLocations()
insertLocation()
getAuthState()
val flushed = BackgroundGeolocation.sync() // upload nowval pending = BackgroundGeolocation.getCount() // how many are waitingval records = BackgroundGeolocation.getLocations() // read without uploadingBackgroundGeolocation.destroyLocation(uuid) // drop oneval dropped = BackgroundGeolocation.destroyLocations()BackgroundGeolocation.insertLocation(json) // inject oneval tokens = BackgroundGeolocation.getAuthState()sync() returns the records it flushed. It ignores
disableAutoSyncOnCellular — an explicit sync is an explicit instruction.
getAuthState() returns the token pair the engine currently holds, which
matters when the engine refreshed a JWT natively and your app keeps its own
copy. See HTTP & authorization.
Logger
getLog()
uploadLog()
destroyLog()
BackgroundGeolocation.logger.info("checkout started", JSONObject().put("cart", 3))
val entries = BackgroundGeolocation.getLog(limit = 200)val uploaded = BackgroundGeolocation.uploadLog()val deleted = BackgroundGeolocation.destroyLog()Your lines land in the same on-device log as the engine’s diagnostics and ride
the same upload path to logUrl, so an app event and the engine’s reaction to
it sit next to each other on one timeline. logger.error/warn/info/debug/verbose
mirror the levels in
LogLevel; anything above the
configured level is dropped rather than stored.
See Logging & debugging.
Events
onLocation, onMotionChange, onProviderChange, onHeartbeat, onHttp,
onConnectivityChange, onPowerSaveChange, onAuthorization,
onLocationError, onGeofence, onGeofencesChange, and the matching Flow
properties — all in Events.