Skip to content
Support the creatorSupport

Get location every N seconds in the background

The first version most apps write is a setInterval that asks for the current position every few seconds. It works on the desk with the screen on. Lock the phone or switch apps and the fixes stop. The code isn’t wrong; it is asking the operating system for something it doesn’t do.

  • iOS suspends an app shortly after it leaves the screen, unless the app has a reason to stay awake. A suspended app runs no code, so setInterval stops with it.
  • Android keeps the process around longer, but React Native pauses its JavaScript timers when the app goes to the background, and an ordinary background app can be frozen or killed at any time to save memory or battery.
  • Scheduled background work is no substitute. Android’s periodic background jobs run at most every 15 minutes, and iOS background refresh runs when iOS decides. Neither is a clock.

What both systems do keep running is a location request the app holds open:

  • On iOS, continuous location updates with the location background mode. While they run, iOS keeps the app alive in the background.
  • On Android, a foreground service of type location, with its notification, holding a request to the fused location provider.

So the reliable pattern is the reverse of a timer: keep one continuous location request open in native code, and pick out the fixes that fall on your schedule. That is what Long Ping does, with no JavaScript involved.

You set two intervals, and the device decides from its own fixes (speed and distance, not a motion classifier) which one applies:

  • movingIntervalSec, default 30 s;
  • parkedIntervalSec, default 180 s.

Each accepts anything from 1 second to 86,400 seconds (24 hours). A switch between moving and parked is recorded immediately, whatever the interval.

A fix is recorded when at least interval − tolerance has passed since the last recorded one. The tolerance is min(0.5 s, 10 % of the interval), so a 10 s interval records a fix every 10 s on both platforms. Fixes less accurate than minAccuracyM (default 100 m) are skipped, unless a fix is more than 30 s overdue: then the most accurate one seen is recorded anyway. And if no fix arrives at all for max(2 × interval, interval + 60 s), a 60-second watchdog logs it and restarts location updates.

Long Ping asks the fused provider for updates at your interval, with no batched delivery. The provider still runs on its own clock: about once per interval, often a little early, and sometimes much earlier when another app’s request wakes it. An early fix is skipped, and on its own that would leave the next fix a whole interval away. So a skipped fix schedules one fresh fix for the moment the interval is due (at least 1 s later), and any recorded fix cancels it.

Location updates run the whole time tracking is on, because they are what keeps the app alive. With your configured accuracy on, iOS delivers a fix about every second, and Long Ping records the one that is due.

For intervals of 60 s or more, Long Ping asks for 3 km accuracy between fixes, which lets the GPS rest, and switches back to your configured accuracy 15 s before the next fix is due. Below 60 s there isn’t enough time between fixes for that to pay off, so the configured accuracy stays on. More in How iOS background tracking works.

lowBattery puts a floor under the interval. When the phone is not charging and the battery is below belowPct percent, the effective interval becomes at least intervalSec, for moving and parked alike. It switches back as soon as the phone charges or the level rises.

Taking a fix and sending it run on separate clocks. With http.uploadIntervalSec: 0 (the default), a request goes out as soon as each fix is recorded: at a 5 s interval, 12 requests a minute. Set it to N and uploads run at most once every N seconds; with batch: true (the default), each request carries up to maxBatchSize records (100) until the queue is empty. sync() sends the queue now, ignoring the interval.

Every record keeps the time of its own fix, so batching changes when your server sees a point, not when or where it was taken. The starting points in these docs are 10–15 s uploads for live dispatch and customer ETAs, 60 s for fleet tracking and 300 s for timesheets. Retries are covered in Offline queue, retries & backoff.

import LongPing from 'react-native-long-ping';
await LongPing.configure({
movingIntervalSec: 10, // a fix every 10 s while moving
parkedIntervalSec: 300, // every 5 minutes while parked
lowBattery: { belowPct: 20, intervalSec: 60 },
http: {
url: 'https://api.example.com/locations',
batch: true,
uploadIntervalSec: 60, // one request a minute, about 6 fixes each while moving
},
});
await LongPing.start();

Any of these can change at runtime with setConfig(), or for a whole fleet from your server with remote config.

  • The moving interval, by far. Below about a minute the GPS is effectively on all the time.
  • Accuracy. 'balanced' and 'low' cost less and are much less precise; for vehicles on roads, 'high' (the default) is usually worth it.
  • Uploads cost radio time: fewer, larger requests are cheaper.
  • The parked interval only helps if the device notices it has stopped: by default, after 300 s within 75 m.
  • The shift. The cheapest fix is the one you never take: start() when someone goes on duty, stop() when they go off.

At 10 s or faster while moving, plan for the phone to charge in the vehicle. The calculator in Choosing intervals & battery estimates fixes, requests, data and battery for any combination.