Methods
Import the default export — every method below is a property of it:
import BackgroundGeolocation from '@dc-bgeo/react-native-background-geolocation';Event listeners (onLocation, onProviderChange, onHttp, onGeofence,
onGeofencesChange, …) have their own page: see the
Events reference. This page covers every
documented method, grouped into: Lifecycle, Geolocation, Permissions &
sensors, Odometer, HTTP & upload queue, Authorization, Geofences, Logging,
Events management, and Headless — see the
Geofencing guide for proximity slicing
and DWELL semantics alongside the geofence methods below.
All methods at a glance
| Method | Purpose |
|---|---|
ready() | Apply config at launch; auto-resumes tracking if it was left enabled. |
setConfig() | Merge config into the live tracker. |
start() | Begin tracking. |
stop() | Stop tracking. |
getState() | Read the current state snapshot without side effects. |
changePace() | Force the motion state machine into moving/stationary. |
getCurrentPosition() | Request a single fix. |
watchPosition() | Start a continuous fix stream via callbacks. |
stopWatchPosition() | Stop the watchPosition() stream. |
requestPermission() | Run the staged permission-request flow. |
requestTemporaryFullAccuracy() | iOS: request temporary full accuracy after Reduced Accuracy. |
getProviderState() | One-shot snapshot of the location provider/authorization. |
isPowerSaveMode() | Read the OS power-saving state. |
getOdometer() | Read the cumulative odometer, metres. |
setOdometer() | Set the odometer to a new value. |
resetOdometer() | Zero the odometer (alias for setOdometer(0)). |
sync() | Manually drain the upload queue. |
getLocations() | Read every queued record, oldest-first. |
destroyLocations() | Delete every queued record. |
getCount() | Count of records currently queued. |
destroyLocation() | Delete one queued record by uuid. |
insertLocation() | Manually enqueue a location-shaped record. |
getAuthState() | Read the tokens the native uploader currently holds. |
addGeofence() | Add (or overwrite) one geofence. |
addGeofences() | Bulk add/overwrite geofences. |
removeGeofence() | Remove one geofence by identifier. |
removeGeofences() | Remove every geofence. |
getGeofences() | Read the full persisted geofence set. |
geofenceExists() | Whether a geofence with a given identifier is persisted. |
logger | Write app-side log lines (error/warn/info/debug/verbose). |
getLog() | Read persisted log entries, newest-first. |
destroyLog() | Delete every persisted log entry. |
uploadLog() | Manually trigger a log upload. |
removeListeners() | Detach every listener and any active watchPosition(). |
registerHeadlessTask() | Android: register a task invoked while the JS context isn’t running. |
Callback vs. promise contract
ready(), setConfig(), start(), and stop() all accept an optional
success/failure callback pair and return a Promise. The two do not
compose the way you’d expect from a typical Promise wrapper. As the source
puts it (matching Transistor):
Note on lifecycle methods (ready/setConfig/start/stop): matching Transistor, when a
failurecallback is supplied the returned promise RESOLVES with the error (after invokingfailure) instead of rejecting; withoutfailureit rejects normally. Call the promise-only form if you want.catchto fire.
In practice:
// failure supplied: on error, failure(err) runs, then the promise RESOLVES with err.// .catch below never fires — .then does, with `state` holding the error object.BackgroundGeolocation.ready(config, undefined, (error) => { console.warn('ready failed', error);}).then((state) => { /* state may actually be the error object here */ });
// no failure callback: standard rejection — this is the form you want for try/catch.try { const state = await BackgroundGeolocation.ready(config);} catch (error) { console.warn('ready failed', error);}If you want a plain Promise you can await/.catch, omit failure entirely.
Lifecycle
ready()
function ready( config: Config, success?: (state: State) => void, failure?: (error: any) => void,): Promise<State>| Parameter | Type | Description |
|---|---|---|
config | Config | Full SDK configuration. |
success | (state: State) => void | Optional. See callback vs. promise contract. |
failure | (error: any) => void | Optional. |
Returns: Promise<State> — applies config and, if tracking was previously enabled, auto-resumes it. In a release build with an invalid or missing license key, rejects (or resolves-with-error, per the contract above) with one of the LICENSE_* codes.
const state = await BackgroundGeolocation.ready({ desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH, distanceFilter: 30, stopOnTerminate: false, startOnBoot: true, url: 'https://your-server.example/locations',});console.log(state.enabled, state.trackingActive);setConfig()
function setConfig( config: Config, success?: (state: State) => void, failure?: (error: any) => void,): Promise<State>| Parameter | Type | Description |
|---|---|---|
config | Config | Partial or full configuration, merged into the live tracker. |
success | (state: State) => void | Optional. |
failure | (error: any) => void | Optional. |
Returns: Promise<State> — the merged state. Same callback/promise contract as ready(). Some keys (e.g. locationFilterPolicy, kalmanProfile) only take effect the next time the filter is rebuilt at tracking start/stop, not immediately — see the Config reference for which keys apply live.
await BackgroundGeolocation.setConfig({ distanceFilter: 50 });start()
function start( success?: (state: State) => void, failure?: (error: any) => void,): Promise<State>Returns: Promise<State> — begins tracking. Rejects with a LICENSE_* code in a release build with an invalid key, per the same callback vs. promise contract as ready().
await BackgroundGeolocation.start();stop()
function stop( success?: (state: State) => void, failure?: (error: any) => void,): Promise<State>Returns: Promise<State> — stops tracking.
await BackgroundGeolocation.stop();getState()
function getState(): Promise<State>Returns: Promise<State> — the current state snapshot without side effects.
const { enabled, isMoving, odometer } = await BackgroundGeolocation.getState();changePace()
function changePace(isMoving: boolean): Promise<void>| Parameter | Type | Description |
|---|---|---|
isMoving | boolean | Force the motion state machine into moving (true) or stationary (false). |
Returns: Promise<void> — rejects DISABLED if tracking is currently stopped. See the tracking lifecycle guide for how this interacts with the automatic motion-detection state machine.
await BackgroundGeolocation.changePace(true); // force movingGeolocation
getCurrentPosition()
function getCurrentPosition(options?: CurrentPositionOptions): Promise<Location>| Parameter | Type | Description |
|---|---|---|
options.persist | boolean | Optional. Whether the fix is added to the upload queue like a normal tracked point. |
options.samples | number | Optional. Number of fixes to sample before returning the best one. |
options.timeout | number | Optional. Seconds to wait before giving up. Default 30. |
options.maximumAge | number | Optional. Accept a cached fix up to this many milliseconds old. |
options.desiredAccuracy | number | Optional. One of the DESIRED_ACCURACY_* constants. |
options.extras | object | Optional. Merged into the returned location’s extras. |
Returns: Promise<Location> — a single fix. Like ready()/start(), rejects with a LICENSE_* code in a release build with an invalid key.
const location = await BackgroundGeolocation.getCurrentPosition({ samples: 3, timeout: 30, // seconds desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,});watchPosition()
function watchPosition( success: (location: Location) => void, failure?: (errorCode: number) => void, options?: WatchPositionOptions,): void| Parameter | Type | Description |
|---|---|---|
success | (location: Location) => void | Called for every fix in the continuous stream. |
failure | (errorCode: number) => void | Optional. Called with a numeric error code — the native { code, message } error payload is unwrapped to just the code before it reaches this callback. |
options.interval | number | Optional. Desired update interval (ms). |
options.desiredAccuracy | number | Optional. One of the DESIRED_ACCURACY_* constants. |
options.persist | boolean | Optional. Whether fixes are added to the upload queue. |
options.extras | object | Optional. Merged into each returned location’s extras. |
Returns: void — this is the one callback-only method with no promise return at all. Internally, fixes from watchPosition ride the same native location event as onLocation, but are distinguished by an extras.watch marker the native side sets; only fixes carrying that marker reach your success callback here. Calling watchPosition() again replaces any previous watch — only one active watch is supported at a time. As with getCurrentPosition(), a LICENSE_* rejection in a release build surfaces here as failure(code) rather than a promise rejection, since this method has no promise contract to reject.
BackgroundGeolocation.watchPosition( (location) => console.log('fix', location.coords), (errorCode) => console.warn('watch error', errorCode), { interval: 2000, desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH },);stopWatchPosition()
function stopWatchPosition(): Promise<void>Returns: Promise<void> — removes the success/failure subscriptions registered by watchPosition() and stops the native watch.
await BackgroundGeolocation.stopWatchPosition();Permissions & sensors
requestPermission()
function requestPermission(): Promise<number>Returns: Promise<number> — one of the AUTHORIZATION_STATUS_* constants. On Android 10+, this runs a staged chain: fine location → background (ACCESS_BACKGROUND_LOCATION, only requested when locationAuthorizationRequest: 'Always') → activity recognition; it early-returns only once both background and activity-recognition are already granted, so the activity-recognition prompt is never silently skipped. On iOS, this method requests location authorization only — see the permissions guide for the full store-declaration requirements on both platforms.
const status = await BackgroundGeolocation.requestPermission();if (status === BackgroundGeolocation.AUTHORIZATION_STATUS_ALWAYS) { await BackgroundGeolocation.start();}requestTemporaryFullAccuracy()
iOSfunction requestTemporaryFullAccuracy(purpose: string): Promise<number>| Parameter | Type | Description |
|---|---|---|
purpose | string | Must exactly match a key in the app’s NSLocationTemporaryUsageDescriptionDictionary in Info.plist — see the permissions guide. |
Returns: Promise<number> — resolves ACCURACY_AUTHORIZATION_FULL (0) or ACCURACY_AUTHORIZATION_REDUCED (1) on iOS 14+. Resolves 0 unconditionally on Android and on iOS below 14.
try { const accuracy = await BackgroundGeolocation.requestTemporaryFullAccuracy('DeliverFullAccuracy');} catch (error) { console.warn('temporary accuracy request failed', error);}getProviderState()
function getProviderState(): Promise<{ status: number; enabled: boolean; gps: boolean; network: boolean; [key: string]: any }>Returns: Promise<{ status, enabled, gps, network, … }> — a one-shot snapshot of the location provider. status is one of the AUTHORIZATION_STATUS_* constants; enabled/gps/network reflect whether location services and the individual GPS/network providers are currently on — see the iOS caveat below. This is the same shape delivered by the onProviderChange event on the Events reference.
const { status, enabled, gps } = await BackgroundGeolocation.getProviderState();On iOS, enabled, gps, and network all reflect the same underlying
“location services enabled” flag — there is no independent GPS-vs-network
provider distinction on that platform. On Android they’re independent: gps
and network reflect the actual state of each provider.
isPowerSaveMode()
function isPowerSaveMode(): Promise<boolean>Returns: Promise<boolean> — the current OS power-saving state: Android battery saver, or iOS Low Power Mode.
const saving = await BackgroundGeolocation.isPowerSaveMode();Odometer
getOdometer()
function getOdometer(): Promise<number>Returns: Promise<number> — the current odometer reading in metres.
const metres = await BackgroundGeolocation.getOdometer();setOdometer()
function setOdometer(value: number): Promise<Location>| Parameter | Type | Description |
|---|---|---|
value | number | New odometer value, in metres. |
Returns: Promise<Location> — resolves with the current location at the moment the odometer was set. That Location is a sample fix (sample: true, event: 'odometer'), not a record from the ambient tracking stream.
await BackgroundGeolocation.setOdometer(0);resetOdometer()
function resetOdometer(): Promise<Location>Returns: Promise<Location> — zeroes the odometer. This is exactly setOdometer(0): a thin JS-side alias with no separate native call, so it resolves the current Location for the same reason setOdometer() does (Transistor semantics — the odometer methods resolve the reference fix used to (re)anchor the reading, not the odometer value itself).
await BackgroundGeolocation.resetOdometer();HTTP & upload queue
See the HTTP upload & authorization guide for the full picture of how url, autoSync, and the SQLite-backed queue interact.
sync()
function sync(): Promise<Location[]>Returns: Promise<Location[]> — manually drains the upload queue. The resolved array is a snapshot of the queue taken before the drain starts, not what remains afterward: internally, sync() first reads the currently-queued records, then tells the native side to drain the queue, and finally resolves with the records it captured in that first read. If more records are enqueued concurrently, they are not included in the resolved array even though they may also be uploaded in the same drain.
const drained = await BackgroundGeolocation.sync();console.log(`uploading ${drained.length} queued records`);getLocations()
function getLocations(): Promise<Location[]>Returns: Promise<Location[]> — every record currently queued for upload, oldest-first.
const queued = await BackgroundGeolocation.getLocations();destroyLocations()
function destroyLocations(): Promise<number>Returns: Promise<number> — deletes every queued record and resolves with the number removed.
const removed = await BackgroundGeolocation.destroyLocations();getCount()
function getCount(): Promise<number>Returns: Promise<number> — the number of records currently queued for upload.
const count = await BackgroundGeolocation.getCount();destroyLocation()
function destroyLocation(uuid: string): Promise<void>| Parameter | Type | Description |
|---|---|---|
uuid | string | The queued record’s uuid. |
Returns: Promise<void> — deletes one queued record. Rejects NOT_FOUND if no queued record has that uuid.
try { await BackgroundGeolocation.destroyLocation(location.uuid);} catch (error) { // error.code === 'NOT_FOUND' if it was already gone (e.g. already synced and pruned).}insertLocation()
function insertLocation(location: Partial<Location> & Record<string, unknown>): Promise<void>| Parameter | Type | Description |
|---|---|---|
location | Partial<Location> & Record<string, unknown> | A location-shaped record to enqueue manually. |
Returns: Promise<void> — enqueues the record through the normal persist path, so autoSync applies to it exactly like a tracked fix. If location.uuid is already present in the queue, the insert is silently ignored (uuid dedup) rather than creating a duplicate or rejecting.
await BackgroundGeolocation.insertLocation({ uuid: 'manual-checkin-1', timestamp: new Date().toISOString(), coords: { latitude: 52.23, longitude: 21.01, accuracy: 5 },});Authorization
getAuthState()
function getAuthState(): Promise<{ accessToken: string | null; refreshToken: string | null }>Returns: Promise<{ accessToken, refreshToken }> — the tokens the native uploader currently holds, from config.authorization. The native side may have refreshed them while the app was killed (a background HTTP 401/403 triggers /auth/refresh with no JS context involved), so your app should prefer this over its own persisted copy on foreground to avoid resuming with a token the server has already invalidated. See the HTTP guide’s authorization section and the onAuthorization event on the Events reference for the corresponding push notification of refresh outcomes.
const { accessToken, refreshToken } = await BackgroundGeolocation.getAuthState();// On app foreground, reconcile these against your in-memory/store copy.Geofences
Full CRUD is available at any time (tracking does not need to be started);
geofences persist in the SDK’s own SQLite database and survive app restarts
and reboots. Only a proximity-sliced subset is registered with the OS at any
moment — see the Geofencing guide for
proximity slicing, the platform registration budget, and DWELL semantics.
Transitions themselves are delivered via the onGeofence/onGeofencesChange
events — see the Events reference; they
are not documented on this page.
addGeofence()
function addGeofence(geofence: Geofence): Promise<void>| Parameter | Type | Description |
|---|---|---|
geofence | Geofence | { identifier, radius, latitude, longitude, notifyOnEntry?, notifyOnExit?, notifyOnDwell?, loiteringDelay?, extras? }. |
Returns: Promise<void> — adds one geofence. An existing geofence with the same identifier is overwritten and re-registered with the fresh values rather than duplicated. Rejects INVALID_GEOFENCE for a malformed geofence — see the Geofencing guide for the validation rules.
await BackgroundGeolocation.addGeofence({ identifier: 'home', radius: 150, latitude: 52.2297, longitude: 21.0122, notifyOnEntry: true, notifyOnExit: true,});addGeofences()
function addGeofences(geofences: Geofence[]): Promise<void>| Parameter | Type | Description |
|---|---|---|
geofences | Geofence[] | Bulk variant of addGeofence() — pass a plain array. |
Returns: Promise<void> — adds (or overwrites, per-identifier) every geofence in the array. Internally the JS layer wraps the array as { geofences: [...] } before it crosses the native bridge (the codegen UnsafeObject boundary marshals as a map, not an array) — this is purely an implementation detail and doesn’t change the call signature for you.
await BackgroundGeolocation.addGeofences([ { identifier: 'home', radius: 150, latitude: 52.2297, longitude: 21.0122, notifyOnEntry: true }, { identifier: 'office', radius: 100, latitude: 52.2319, longitude: 21.0067, notifyOnEntry: true, notifyOnExit: true },]);removeGeofence()
function removeGeofence(identifier: string): Promise<void>| Parameter | Type | Description |
|---|---|---|
identifier | string | The geofence’s identifier. |
Returns: Promise<void> — removes the one geofence matching identifier.
await BackgroundGeolocation.removeGeofence('office');removeGeofences()
function removeGeofences(): Promise<void>Returns: Promise<void> — removes all geofences (Transistor semantics) — the whole persisted set, not just the subset currently registered with the OS.
await BackgroundGeolocation.removeGeofences();getGeofences()
function getGeofences(): Promise<Geofence[]>Returns: Promise<Geofence[]> — the full persisted set, not just the proximity-sliced subset currently registered with the OS.
const geofences = await BackgroundGeolocation.getGeofences();geofenceExists()
function geofenceExists(identifier: string): Promise<boolean>| Parameter | Type | Description |
|---|---|---|
identifier | string | The geofence’s identifier. |
Returns: Promise<boolean> — whether a geofence with that identifier is currently persisted.
const exists = await BackgroundGeolocation.geofenceExists('home');Logging
See the logging & debugging guide for retention, upload cadence, and field reference.
logger
const logger: { error: (message: string, data?: object, tag?: string) => Promise<void>; warn: (message: string, data?: object, tag?: string) => Promise<void>; info: (message: string, data?: object, tag?: string) => Promise<void>; debug: (message: string, data?: object, tag?: string) => Promise<void>; verbose: (message: string, data?: object, tag?: string) => Promise<void>;}| Parameter | Type | Description |
|---|---|---|
message | string | Log line text. |
data | object | Optional. JSON-serialized and stored alongside the line. |
tag | string | Optional. Android only. Logcat category for this line (adb logcat -s MyTag); default BGGeo. Not persisted in the LogEntry, never uploaded, ignored on iOS. |
Returns: each method returns Promise<void> and never rejects — a logging call must never throw into app code, so failures are swallowed internally. App-written lines are persisted in the same on-device store as native engine logs (tagged src: "js") and uploaded through the same batches described in the logging guide.
BackgroundGeolocation.logger.warn('geofence sync deferred', { pendingCount: 3 });getLog()
function getLog(limit?: number): Promise<LogEntry[]>| Parameter | Type | Description |
|---|---|---|
limit | number | Optional. Maximum number of entries to return. Default 500. |
Returns: Promise<LogEntry[]> — persisted log entries, newest-first.
const recent = await BackgroundGeolocation.getLog(100);destroyLog()
function destroyLog(): Promise<number>Returns: Promise<number> — deletes all persisted log entries and resolves with the number of rows removed.
await BackgroundGeolocation.destroyLog();uploadLog()
function uploadLog(): Promise<number>Returns: Promise<number> — manually triggers a log upload and resolves with the number of rows handed to the flusher (not necessarily the number successfully delivered — retryable failures stay queued).
await BackgroundGeolocation.uploadLog();Events management
removeListeners()
function removeListeners(): voidReturns: void — detaches every listener registered through any on* method on the Events reference (including geofence listeners from the Geofencing guide), and also tears down any active watchPosition() subscription, exactly as if stopWatchPosition() had been called. Call this from your top-level teardown (e.g. on sign-out) rather than removing listeners one at a time.
BackgroundGeolocation.removeListeners();Headless
registerHeadlessTask()
Androidfunction registerHeadlessTask(task: HeadlessTask): void| Parameter | Type | Description |
|---|---|---|
task | (event: HeadlessEvent) => Promise<void> | void | Invoked by the native side when an event fires while the JS context is not running. |
Returns: void. On Android, this registers the task with AppRegistry.registerHeadlessTask so the OS-managed HeadlessJsTaskService can spin up a JS context and invoke it — see the boot & killed-app guide for when this fires. iOS has no headless JS task service; on iOS the task is retained but never registered with AppRegistry, so it is not invoked while the app process isn’t running.
BackgroundGeolocation.registerHeadlessTask(async (event) => { if (event.name === 'heartbeat') { console.log('headless heartbeat', event); }});