Skip to content

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

MethodReturnsNotes
attach(context)UnitMandatory, in Application.onCreate
ready(config)StateConfigure; does not start tracking
setConfig(config)StateChange config on a running engine
start()StateBegin tracking; persists
stop()StateStop tracking
getState()StateSnapshot + health fields
changePace(isMoving)UnitForce the motion state
getCurrentPosition(options)LocationOne-shot fix
watchPosition(options)UnitHigh-frequency stream
stopWatchPosition()Unit
requestPermission(requester)AuthorizationStatusStaged escalation
getProviderState()ProviderStateGrant + provider availability
isPowerSaveMode()Boolean
getOdometer()DoubleMetres
setOdometer(value)Location
resetOdometer()LocationsetOdometer(0.0)
addGeofence(geofence)Unit
addGeofences(list)Unit
removeGeofence(identifier)Unit
removeGeofences()UnitAll of them
getGeofences()List<Geofence>
geofenceExists(identifier)Boolean
sync()List<Location>Flush the queue now
getCount()IntRecords pending
getLocations()List<Location>Read the queue
destroyLocations()IntEmpty the queue
destroyLocation(uuid)UnitDrop one record
insertLocation(json)UnitInject a record
getAuthState()AuthStateCurrent token pair
getLog(limit)List<LogEntry>
destroyLog()Int
uploadLog()Int
logger.info(...) etc.UnitWrite your own lines
onX(handler)SubscriptionSee Events
removeListeners()UnitDetach 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 trackingstate.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 // typed
state["lastAcceptedFixAge"] as? Double // health fields, from raw

See 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, named

The 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 now
val pending = BackgroundGeolocation.getCount() // how many are waiting
val records = BackgroundGeolocation.getLocations() // read without uploading
BackgroundGeolocation.destroyLocation(uuid) // drop one
val dropped = BackgroundGeolocation.destroyLocations()
BackgroundGeolocation.insertLocation(json) // inject one
val 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.