AppConfig¶
classAppConfig
Application and lifecycle configuration for the background geolocation SDK.
AppConfig controls how the SDK integrates with your app's lifecycle: tracking
behavior on terminate and reboot, headless operation, periodic heartbeats,
automated scheduler windows, foreground notifications, and the Android
background-permission rationale dialog.
Contents¶
Overview¶
| Category | Properties | Notes |
|---|---|---|
| Lifecycle | stopOnTerminate, startOnBoot |
Controls tracking across app terminate and device reboot. |
| Headless | enableHeadless |
Android only Tracking continues with no JS/UI process. |
| Heartbeat | heartbeatInterval, preventSuspend |
Periodic background callbacks. preventSuspend is iOS only. |
| Scheduler | schedule, scheduleUseAlarmManager |
Automated start/stop windows. scheduleUseAlarmManager is Android only. |
| Notification | notification |
Android only Foreground service notification. |
| Permission | backgroundPermissionRationale |
Android only Android 11+ background location rationale. |
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
app.stopOnTerminate = false
app.startOnBoot = true
}
Lifecycle¶
AppConfig.stopOnTerminate (default true) controls whether tracking
stops when the user terminates the app. Set to false to continue tracking
after termination — iOS and Android handle this differently:
- iOS creates a stationary geofence and relaunches the app when the device exits it (~200 m). Tracking resumes automatically.
- Android continues the native background service headlessly. Pair with HttpConfig.url to ensure uploads continue without the UI layer.
AppConfig.startOnBoot (default false) controls whether tracking
resumes after a device reboot. On Android, the background service restarts
automatically. On iOS, the OS must first wake the app via a stationary geofence
exit or a Background Fetch event.
AppConfig.enableHeadless (default false) allows Android to respond
to SDK events even after the app is terminated. Requires
stopOnTerminate: false. Android only
Heartbeat¶
AppConfig.heartbeatInterval fires BGGeo.onHeartbeat
periodically while the app is in the background. On iOS, this requires
AppConfig.preventSuspend true to keep the app alive. On Android, the
minimum interval is 60 seconds.
AppConfig.preventSuspend (default false) prevents iOS from suspending
the app when location services are inactive. Required for heartbeat support on
iOS but increases battery consumption — use only for specific, time-limited
use cases. iOS only
Scheduler¶
AppConfig.schedule accepts an array of schedule strings that tell the
SDK when to automatically start and stop tracking. Each string follows the
format "DAY(s) HH:mm-HH:mm" using 24h time and Locale.US day numbers
(Sunday=1, Saturday=7).
Call BGGeo.startSchedule to activate the scheduler
after calling ready().
AppConfig.scheduleUseAlarmManager (default false) forces the Android
scheduler to use AlarmManager (exact, on-the-minute) instead of
JobScheduler (inexact). Android only
Background permission¶
Android 11 removed the Allow all the time option from the system location
dialog. Configure AppConfig.backgroundPermissionRationale to show a
custom rationale dialog that routes the user to the system Location Permissions
screen to grant background access. The SDK shows this dialog automatically when
GeolocationConfig.locationAuthorizationRequest is "Always". Android only
See PermissionRationale for the full dialog configuration reference.
Examples¶
Configure once at startup:¶
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
app.stopOnTerminate = false
app.startOnBoot = true
app.enableHeadless = true
app.heartbeatInterval = 60.0
app.backgroundPermissionRationale = mapOf(
"title" to "Allow MyApp to access this device's location even when closed.",
"message" to "This app collects location data to record your trips and mileage.",
"positiveAction" to "Change to \"{backgroundPermissionOptionLabel}\"",
"negativeAction" to "Cancel"
)
app.schedule = listOf("1-5 09:00-17:00") // Weekdays 9-5
app.scheduleUseAlarmManager = true
}
Update later at runtime:¶
val bgGeo = BGGeo.instance
bgGeo.config.edit {
app.heartbeatInterval = 120.0 // slow down heartbeats
}
Members¶
backgroundPermissionRationale¶
Android only Configures the dialog shown when requesting Always background location permission on Android 11 and later.
Android 11 removed the Allow all the time button from the system
permission dialog. Apps may instead present a custom rationale dialog
explaining why background access is required. Selecting the dialog's
positiveAction sends the user directly to the system Location
Permissions screen, where they must enable Allow all the time.
The SDK shows this dialog automatically when
AppConfig.backgroundPermissionRationale is configured and
GeolocationConfig.locationAuthorizationRequest is "Always".
- The rationale dialog is shown once only. After the user presses the
positiveAction, it will not appear again. Pressing Cancel does not count. - If the user later resets your app's Location permission to Ask every time, the dialog may be presented again.

val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
geolocation.locationAuthorizationRequest = LocationAuthorizationRequest.ALWAYS
app.backgroundPermissionRationale = mapOf(
"title" to "Allow {applicationName} to access this device's location in the background?",
"message" to "To track your activity in the background, please enable {backgroundPermissionOptionLabel} location permission.",
"positiveAction" to "Change to {backgroundPermissionOptionLabel}",
"negativeAction" to "Cancel"
)
}
Template tags¶
Embed the following variables inside PermissionRationale
fields using {tagName} syntax:
| Template Tag | Default value | Description |
|---|---|---|
{backgroundPermissionOptionLabel} |
Allow all the time | Localized label for the background permission option (API 30+). |
{applicationName} |
Your app name | From AndroidManifest.xml. |
See also - GeolocationConfig.locationAuthorizationRequest - BGGeo.requestPermission - Location updates in Android 11
enableHeadless¶
Android only Enables headless operation so the SDK can respond to events after the app
has been terminated with AppConfig.stopOnTerminate false. Defaults
to false.
In the headless state only the native foreground service is running — the JS/UI process is gone. Register a callback with BGGeo.registerHeadlessTask to handle events in this state.
Note
- Requires AppConfig.stopOnTerminate
false. - With
stopOnTerminate: false, the SDK records and uploads locations regardless ofenableHeadless. Enable this only if you need to perform custom work during the headless state (for example, posting a local notification).
See also - Android Headless Mode - BGGeo.registerHeadlessTask
heartbeatInterval¶
Rate in seconds at which BGGeo.onHeartbeat events fire while the app is in the background.
iOS¶
Requires AppConfig.preventSuspend true. Defaults to 60 seconds
when enabled.
Android¶
Heartbeat is disabled by default (-1). Set to a positive integer of at
least 60 to enable it. Values below 60 are not supported.
Warning
- On iOS, heartbeat fires only when AppConfig.preventSuspend is
true. - On Android, the minimum supported interval is
60seconds.
See also - BGGeo.onHeartbeat
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
app.heartbeatInterval = 60.0
}
bgGeo.onHeartbeat { event ->
Log.d(TAG, "[onHeartbeat] $event")
// Optionally request a new location during heartbeat.
kotlinx.coroutines.runBlocking {
val location = bgGeo.getCurrentPosition(samples = 1, persist = true)
Log.d(TAG, "[getCurrentPosition] $location")
}
}
notification¶
Android only Configures the persistent foreground-service notification required by Android.

See NotificationConfig for detailed usage.
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
// notification is configured via AndroidManifest.xml or at runtime
// using the Android notification API directly
}
schedule¶
Configures a cron-like automated schedule that tells the SDK when to
start and
stop tracking.
- Times are in 24h format.
DAYuses Locale.US day numbers: Sunday = 1, Saturday = 7.- Day values may be a single day (
"1"), a comma-separated list ("2,4,6"), or a range ("2-6").
// Within a coroutine scope
val bgGeo = BGGeo.instance
bgGeo.ready {
app.schedule = listOf(
"1 17:30-21:00", // Sunday: 5:30pm-9pm
"2-6 09:00-17:00", // Mon-Fri: 9am-5pm
"2,4,6 20:00-00:00", // Mon, Wed, Fri: 8pm-midnight
"7 10:00-19:00" // Saturday: 10am-7pm
)
}
// Start the Scheduler
bgGeo.startSchedule()
// Listen for schedule state changes
bgGeo.onSchedule { event ->
Log.d(TAG, "[onSchedule] enabled? ${event.state}")
}
// Later (e.g., user logout)
bgGeo.stopSchedule()
bgGeo.stop() // if tracking is currently enabled
// Modify schedule using config.edit
bgGeo.config.edit {
app.schedule = listOf(
"1-7 09:00-10:00",
"1-7 11:00-12:00",
"1-7 13:00-14:00",
"1-7 15:00-16:00",
"1-7 17:00-18:00",
"2,4,6 19:00-22:00"
)
}
Literal dates¶
A schedule entry may use a literal date range:
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
app.schedule = listOf("2018-01-01 09:00-17:00")
}
Or specify distinct start and stop dates:
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
app.schedule = listOf("2018-01-01-09:00 2019-01-01-17:00") // track for 1 year
}
Scheduling modes¶
Append geofence or location to explicitly choose a tracking mode.
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
app.schedule = listOf(
"1-7 09:00-17:00 location",
"1-7 18:00-12:00 geofence"
)
}
iOS¶
- iOS cannot evaluate the schedule exactly at the configured time. Evaluation occurs only when the app is awakened.
- During a scheduled off period, iOS continues monitoring low-power
Significant Location Changes (SLC) to guarantee periodic re-evaluation,
especially when AppConfig.stopOnTerminate is
falseand the OS halts traditional Background Fetch. - Schedule evaluation occurs when the app pauses/resumes, any location is recorded (including SLC), or a Background Fetch event fires.
Android¶
Uses AlarmManager.setExactAndAllowWhileIdle, typically evaluating
on-the-minute.
See also - BGGeo.startSchedule - BGGeo.stopSchedule
Since location is the default mode, it may be omitted¶
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
app.schedule = listOf(
"1-7 09:00-17:00 location",
"1-7 18:00-12:00 geofence"
)
}
scheduleUseAlarmManager¶
Android only Forces the Android scheduler to use AlarmManager (exact, on-the-minute)
instead of JobScheduler (inexact). Defaults to false.
val bgGeo = BGGeo.instance
// Within a coroutine scope
bgGeo.ready {
app.schedule = listOf("1-7 09:00-17:00")
app.scheduleUseAlarmManager = true
}
startOnBoot¶
Controls whether tracking resumes automatically after the device reboots.
Defaults to false.
iOS¶
iOS cannot begin tracking immediately after a reboot. Similar to
AppConfig.stopOnTerminate false, the SDK waits until one of the
following occurs:
- The device exits the stationary geofence created around the last known
location.
- A system Background Fetch event fires (typically every ~15 minutes).
Android¶
When true, Android relaunches the SDK background service after reboot and
initial device unlock. If AppConfig.enableHeadless is also true,
tracking resumes even before the JS/UI layer starts.
See also - AppConfig.enableHeadless - AppConfig.stopOnTerminate
stopOnTerminate¶
Controls whether tracking stops when the application is terminated by the
user. Defaults to true.
When true, the SDK calls stop() as the app terminates. Set to false
to keep tracking alive after termination — iOS and Android behave differently
in this state.
iOS¶
Before termination, the SDK registers a stationary geofence of GeolocationConfig.stationaryRadius meters around the last known position. When the device exits that geofence (~200 m), iOS fully relaunches the app in the background and tracking resumes automatically. This mechanism survives device reboot because iOS monitors geofences at the OS level.
Demo video: https://www.youtube.com/watch?v=aR6r8qV1TI8&t=214s

Android¶
Android does not pause tracking when the user terminates the app. The native background service continues running headlessly without the JS/UI process. Configure HttpConfig.url so the service can continue uploading locations to your server.
See also - AppConfig.enableHeadless - Android Headless Mode