Skip to content
Support the creatorSupport

Troubleshooting

Long Ping writes every state change, restart, upload result and rejected fix to a log on the device. When a phone “went quiet”, the log usually says why.

const text = await LongPing.logger.getLog({
sinceMs: Date.now() - 6 * 60 * 60 * 1000, // last 6 hours (default: last 24 hours)
limit: 2000, // newest 2000 entries (default 1000)
order: 'desc', // newest first (default 'asc')
});

One entry per line: timestamp (UTC), level, tag, message.

Example (wording varies by platform and version)
2026-10-26T07:58:02.114Z INFO [engine] tracking started
2026-10-26T07:58:03.870Z INFO [engine] recorded motionchange (moving, ±6 m)
2026-10-26T07:58:33.902Z INFO [engine] recorded interval (moving, ±5 m)
2026-10-26T07:59:04.011Z INFO [http] POST https://api.example.com/locations -> 200, 2 records, 184 ms
2026-10-26T08:41:15.330Z WARN [http] upload failed (network error); next attempt in 11 s
2026-10-26T08:44:02.508Z INFO [engine] now parked
2026-10-26T09:52:40.001Z WARN [engine] no fix for 312 s; restarting location updates
  • logLevel (default 'info') controls how much is written; 'debug' adds skipped fixes, ignored config keys and more. Use it while testing.
  • Entries are kept for logMaxDays (default 3, up to 30).
  • logger.clear() deletes the log.

Add a “Send diagnostics” action to your app and post the log to your server:

async function sendDiagnostics() {
const [log, state, provider] = await Promise.all([
LongPing.logger.getLog({ sinceMs: Date.now() - 24 * 60 * 60 * 1000 }),
LongPing.getState(),
LongPing.getProviderState(),
]);
await fetch('https://api.example.com/diagnostics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ log, state, provider }),
});
}

getProviderState() alone answers a lot: permission level, precise or reduced accuracy, location services, power-save mode and (Android) battery-optimization exemption.

  • start() rejected: check for PERMISSION_DENIED or LOCATION_SERVICES_OFF.
  • iOS: UIBackgroundModes → location is missing, so tracking stops in the background. The log has an error about it. See Installation.
  • Android: the device has no Google Play Services (v0.1 uses the fused provider only).
  • All fixes are less accurate than minAccuracyM (indoors, reduced accuracy on iOS). One is still recorded when a fix is overdue by 30 s; logLevel: 'debug' shows the rejected ones.

Almost always an OEM battery manager freezing the app. Look for “no fix for … s; restarting location updates” or “service restarted by the system” when it came back. Walk the user through Android battery managers.

Gaps on iPhone after the app was swiped away

Section titled “Gaps on iPhone after the app was swiped away”

Expected: iOS stops a swiped-away app until the device moves a few hundred meters, then relaunches it. See How iOS background tracking works. Set stopOnTerminate: true if you want a swipe-away to stop tracking instead.

Fixes are recorded but nothing reaches the server

Section titled “Fixes are recorded but nothing reaches the server”

Check getState() and the http lines in the log:

You see Cause
No http lines at all http.url is null or '' (record-only mode).
authorizationRequired: true, “uploads paused” 401/403 and no working refresh. Call setAuthorization(); see Authentication.
“upload failed …; next attempt in N s” Network errors, 408, 429 or 5xx: backoff, up to 15 minutes. sync() retries now.
Status 0 on every attempt No connectivity, DNS, TLS, or (in development) cleartext HTTP blocked by ATS / network security config.
  • “dropped N records after 3 rejected attempts”: your server answered a 4xx other than 401, 403, 408, 413 or 429 three times. Answer 2xx for batches you can mostly use.
  • “queue pruned”: the queue hit persistence.maxRecords or records got older than persistence.maxDays while the device couldn’t upload.

Retries after a lost reply resend records. Deduplicate on uuid; see Receiving uploads.

Never switches to parked, or flips back and forth

Section titled “Never switches to parked, or flips back and forth”
  • GPS drift where you park is larger than stopRadiusM (75 m): raise it.
  • Stops are shorter than stopTimeoutSec (300 s): lower it, if you want short stops to count.
  • Walking around with the phone above movingSpeedMps (3 m/s) counts as moving.
  • disableStopDetection: true never parks.
  • lowBattery is set, the phone isn’t charging and the battery is below belowPct.
  • Fixes are being filtered by minAccuracyM until one is overdue.
  • The device is parked and on parkedIntervalSec.
  • A remote config changed the interval (look for “server config applied” / configchange).

Long Ping never stops on its own. Only stop() or a server reply with {"long_ping": {"stop": true}} stops tracking (both are logged), or, with stopOnTerminate: true, the app being terminated. Auth failures, network failures and bad responses only pause or retry uploads.

Your app hasn’t been granted POST_NOTIFICATIONS. Tracking still runs; the notification is hidden.