Config
Pass a Config object to configure() (replace) or setConfig() (merge). Every key is optional.
import LongPing, { type Config } from 'react-native-long-ping';How config is applied
Section titled “How config is applied”| Call | Behaviour |
|---|---|
configure(config) |
Replaces the whole config with the defaults plus config, validates, saves and applies it live. Never starts, stops or prompts. Safe on every launch. |
setConfig(partial) |
Deep-merges into the current config: objects merge, arrays and scalars replace. Validates, saves, applies. |
Server reply long_ping.config |
Stored as a separate layer on top of the app’s config (it survives configure()), applied when remoteConfig is true. long_ping.reset clears it. See Remote config. |
Both calls resolve the new State, whose config field holds the full
resolved config.
Validation rules:
- A value of the wrong type rejects with
INVALID_CONFIG; the message names the key (for examplehttp.url). - Numbers outside their range are clamped into it, not rejected.
nullon a key that is not nullable means “use the default”.''on a nullable string meansnull.- Unknown keys are ignored and logged at
debuglevel. http.urlmust be an absolutehttp://orhttps://URL.lowBatteryneeds both fields.- A negative
minAccuracyMrejects withINVALID_CONFIG. http.locationTemplateis checked by rendering a sample record and parsing the result as JSON; an unknown token or invalid JSON rejects withINVALID_CONFIG.
The config is saved on the device (Android SharedPreferences, iOS UserDefaults). Upload credentials are
never part of it; they go through setAuthorization().
All defaults
Section titled “All defaults”{ movingIntervalSec: 30, parkedIntervalSec: 180, accuracy: 'high', minAccuracyM: 100, stopTimeoutSec: 300, stopRadiusM: 75, movingSpeedMps: 3, disableStopDetection: false, lowBattery: null, http: { url: null, method: 'POST', headers: {}, batch: true, maxBatchSize: 100, uploadIntervalSec: 0, rootProperty: null, locationTemplate: null, params: {}, extras: {}, timeoutSec: 30, }, persistence: { maxRecords: 10000, maxDays: 7 }, startOnBoot: true, stopOnTerminate: false, remoteConfig: true, notification: { title: 'Location tracking', text: 'Sharing your location', channelName: 'Location tracking', smallIcon: null, priority: 'low', }, ios: { showsBackgroundLocationIndicator: false, activityType: 'automotive' }, logLevel: 'info', logMaxDays: 3, debug: false,}Intervals
Section titled “Intervals”| Key | Type | Default | Range |
|---|---|---|---|
movingIntervalSec |
number |
30 |
1 – 86400 |
parkedIntervalSec |
number |
180 |
1 – 86400 |
lowBattery |
object | null |
null |
see below |
movingIntervalSec: seconds between recorded fixes while moving.
parkedIntervalSec: seconds between recorded fixes while parked.
lowBattery: { belowPct: number; intervalSec: number }. When the phone is not charging and the battery is
below belowPct percent (0–100), the interval becomes at least intervalSec seconds (1–86400). Both fields are
required. null turns it off.
The effective interval is recomputed on every fix, on every motion change, config change and battery change:
base = isMoving ? movingIntervalSec : parkedIntervalSecif lowBattery != null && !charging && batteryPct < lowBattery.belowPct: base = max(base, lowBattery.intervalSec)A fix is recorded when at least interval − tolerance has passed since the last recorded fix, where
tolerance is min(0.5 s, 10 % of the interval), so a 10 s interval records a fix every 10 s on both
platforms. Motion changes are always recorded immediately. On iOS,
intervals of 60 s or more use a low-power mode between fixes; see
How iOS background tracking works.
Accuracy
Section titled “Accuracy”| Key | Type | Default | Range |
|---|---|---|---|
accuracy |
'high' | 'balanced' | 'low' |
'high' |
|
minAccuracyM |
number |
100 |
≥ 0; 0 accepts any accuracy |
accuracy sets what the OS is asked for:
| Value | Android (fused provider priority) | iOS (desiredAccuracy when a fix is taken) |
|---|---|---|
'high' |
PRIORITY_HIGH_ACCURACY |
kCLLocationAccuracyBest |
'balanced' |
PRIORITY_BALANCED_POWER_ACCURACY |
kCLLocationAccuracyHundredMeters |
'low' |
PRIORITY_LOW_POWER |
kCLLocationAccuracyKilometer |
minAccuracyM: fixes with a horizontal accuracy worse than this many meters are not recorded. If a fix
is overdue (more than interval + 30 s since the last record) and only inaccurate fixes arrived, the most
accurate one seen is recorded anyway, and the log says so.
Stop detection
Section titled “Stop detection”Moving and parked are decided from the fixes (speed and displacement), never from an OS activity classifier. The rules are identical on both platforms.
| Key | Type | Default | Range |
|---|---|---|---|
stopTimeoutSec |
number |
300 |
30 – 86400 |
stopRadiusM |
number |
75 |
10 – 10000 |
movingSpeedMps |
number |
3 |
0.5 – 100 |
disableStopDetection |
boolean |
false |
stopTimeoutSec: how long the device has to stay within stopRadiusM before it counts as parked.
stopRadiusM: the radius, in meters, that counts as “not going anywhere”. On iOS a region of radius
max(100, stopRadiusM × 2) is also monitored while parked; leaving it switches back to moving immediately.
movingSpeedMps: a speed, in meters per second, that counts as moving (3 m/s ≈ 11 km/h ≈ 6.7 mph).
disableStopDetection: true keeps the device in the moving state for as long as tracking is on.
How the state changes:
- Moving → parked: the device has stayed within
stopRadiusMof an anchor fix, belowmovingSpeedMps, forstopTimeoutSec. - Parked → moving: a fix at or above
movingSpeedMpswith accuracy ≤ 50 m, or a fix more thanstopRadiusMfrom the parked position with accuracy ≤stopRadiusM.
Only fixes with accuracy ≤ max(minAccuracyM, stopRadiusM) are evaluated. You can force either state with
changePace().
| Key | Type | Default | Range / values |
|---|---|---|---|
url |
string | null |
null |
Absolute http(s) URL. null or '' = record only, never upload. |
method |
'POST' | 'PUT' |
'POST' |
|
headers |
Record<string, string> |
{} |
Sent with every upload. |
batch |
boolean |
true |
|
maxBatchSize |
number |
100 |
1 – 1000 |
uploadIntervalSec |
number |
0 |
0 – 86400 |
rootProperty |
string | null |
null |
Any key, or '.' |
locationTemplate |
string | null |
null |
JSON template with {{tokens}} |
params |
object |
{} |
Merged into the body root. |
extras |
object |
{} |
Added to every record as extras. |
timeoutSec |
number |
30 |
5 – 120 |
url: the upload endpoint. Without it, fixes are still recorded, stored and emitted to JavaScript, but
nothing is uploaded.
headers: added to every upload. When an access token is stored, Authorization: Bearer <token> is
added too and wins over an Authorization header set here.
batch: true sends up to maxBatchSize records per request under locations. false sends one
request per record under location.
uploadIntervalSec: 0 uploads as soon as a fix is recorded. N means at most one upload every N
seconds. sync() ignores it.
rootProperty: where the records go in the body. null means 'locations' (batch) or 'location'
(single). '.' puts a single record’s fields at the body root; with batch: true, '.' falls back to
'locations'.
locationTemplate: replaces the default record JSON, per record. Tokens are replaced with raw JSON
values and strings go in without quotes, so write them yourself:
'{"lat":{{latitude}},"lng":{{longitude}},"at":"{{timestamp}}"}'. Tokens: uuid, timestamp, event,
is_moving, latitude, longitude, accuracy, speed, heading, altitude, battery_level,
battery_is_charging, mock, extras (JSON object text).
params: merged into the root of every request body.
extras: added to every record as an extras object (merged with any per-call extras from
getCurrentPosition(); the record only has extras when the result is non-empty).
timeoutSec: per request.
The exact request and response rules are in the HTTP contract; try them in the playground in Receiving uploads.
persistence
Section titled “persistence”| Key | Type | Default | Range |
|---|---|---|---|
persistence.maxRecords |
number |
10000 |
1 – 1000000 |
persistence.maxDays |
number |
7 |
1 – 365 |
The on-device queue keeps at most maxRecords records and nothing older than maxDays days. It is pruned
after each insert, oldest first, and pruning is logged with counts.
Lifecycle
Section titled “Lifecycle”| Key | Type | Default |
|---|---|---|
startOnBoot |
boolean |
true |
stopOnTerminate |
boolean |
false |
remoteConfig |
boolean |
true |
startOnBoot: on Android, tracking that was enabled resumes after a reboot or an app update without
the app being opened. With false it waits until the app is opened. On iOS, relaunching after termination
comes from significant-change and region monitoring; see
How iOS background tracking works.
stopOnTerminate: true stops tracking when the app is terminated (swiped away). With the default
false, iOS keeps significant-change and region monitoring on so it can relaunch the app.
remoteConfig: apply long_ping.config from upload replies. Only the app can set it. A long_ping.stop or
long_ping.reset from the server is honoured regardless.
notification (Android)
Section titled “notification (Android)”The foreground-service notification shown while tracking on Android. Ignored on iOS.
| Key | Type | Default | Notes |
|---|---|---|---|
notification.title |
string |
'Location tracking' |
|
notification.text |
string |
'Sharing your location' |
|
notification.channelName |
string |
'Location tracking' |
Shown in the app’s notification settings. |
notification.smallIcon |
string | null |
null |
A drawable or mipmap resource name. null = the app icon. |
notification.priority |
'low' | 'default' | 'high' |
'low' |
On Android 13+ the notification is only visible if your app has POST_NOTIFICATIONS; see
Installation.
| Key | Type | Default |
|---|---|---|
ios.showsBackgroundLocationIndicator |
boolean |
false |
ios.activityType |
'automotive' | 'otherNavigation' | 'fitness' | 'other' |
'automotive' |
showsBackgroundLocationIndicator: show the blue location indicator in the status bar while the app
uses location in the background.
activityType: passed to CoreLocation as the activity type.
Logging and debug
Section titled “Logging and debug”| Key | Type | Default | Range / values |
|---|---|---|---|
logLevel |
'off' | 'error' | 'warn' | 'info' | 'debug' |
'info' |
|
logMaxDays |
number |
3 |
1 – 30 |
debug |
boolean |
false |
logLevel and logMaxDays control the on-device log you read with logger.getLog(). See
Troubleshooting.
debug: on Android, the notification text shows the age of the last fix and the queue size.