iOS setup
iOS needs a few Info.plist entries and the right capabilities. There are no AppDelegate changes and no module registration. The package registers itself when your app launches.
Requirements
- iOS 15.1 or newer as the deployment target.
- New Architecture enabled (the default in current React Native versions).
- CocoaPods: run
cd ios && pod installafter installing the package.
1. Enable background modes
In Xcode, select your app target, open Signing & Capabilities, add Background Modes, and check:
- Location updates
- Background fetch
This writes the following to your Info.plist:
<key>UIBackgroundModes</key>
<array>
<string>location</string>
<string>fetch</string>
</array>
2. Register the background task identifier
The recovery watchdog uses a background app refresh task. iOS only runs tasks whose identifiers are listed in Info.plist. The identifier is your bundle ID followed by .bgtrack.watchdog:
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).bgtrack.watchdog</string>
</array>
Using $(PRODUCT_BUNDLE_IDENTIFIER) keeps it correct across schemes and bundle IDs.
3. Add usage descriptions
iOS shows these strings in the permission prompts. App Store review rejects vague text, so describe your actual feature.
<key>NSLocationWhenInUseUsageDescription</key>
<string>We use your location to show your route while you use the app.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We use your location in the background to record your trip even when the app is closed.</string>
<key>NSMotionUsageDescription</key>
<string>We use motion data to pause GPS while you are stationary, which saves battery.</string>
NSMotionUsageDescription is needed only if you use the adaptive_low_power profile, which is the default. Keep it unless you always switch to balanced or continuous_fitness.
Permission flow
iOS grants Always permission in two steps, and you only get one chance to show each prompt:
LocationTracker.requestLocationPermission(true);
- First call: iOS shows the When-In-Use prompt.
- Once When-In-Use is granted, the tracker asks to upgrade to Always.
- If iOS will no longer show a prompt, the app's Settings page opens instead.
Read the result from getStatus().authorization: notDetermined, whenInUse, always, denied or restricted.
| Authorization | What works |
|---|---|
always | Everything: background tracking, relaunch after the app is killed, resume after reboot. |
whenInUse | Tracking while the app is open and shortly after it is backgrounded (with the blue location indicator). No relaunch after kill. |
denied or restricted | Nothing. startTracking() reports [permission_denied]. |
Also check preciseLocation. If the user turned off Precise Location, points are approximate (several kilometers).
Background App Refresh and Low Power Mode
Two system settings affect recovery. Both are exposed in getStatus():
| Field | Meaning on iOS | Fix |
|---|---|---|
exactAlarmsAllowed | Background App Refresh is available for the app. | openExactAlarmSettings() opens the app's Settings page. |
batteryUnrestricted | Low Power Mode is off. | The user must turn off Low Power Mode. requestIgnoreBatteryOptimizations() opens Settings. |
Tracking still runs with these off, but recovery after the app is killed is slower and less reliable.
Cleartext HTTP for local testing
App Transport Security blocks plain http://. For a local test server, allow local networking in debug only, or use an HTTPS tunnel:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
NSAllowsLocalNetworking covers localhost and .local hosts. For a LAN IP on a physical device, use an HTTPS tunnel such as ngrok instead of disabling ATS.
App Store submission checklist
- Usage strings that clearly describe the user-facing feature that needs background location.
- Reviewer notes that explain how to trigger background tracking. Include a demo account if needed.
- A privacy manifest (
PrivacyInfo.xcprivacy) declaring precise location collection and its purpose. - App Privacy answers in App Store Connect that match the privacy manifest.
The licensed editions include ready-made Info.plist and privacy manifest templates plus reviewer notes. See Evaluation vs licensed edition.