react-native-fitness-geolocation
v2.1.0
Published
React Native fitness GPS — background activity tracking, native SQLite persistence, motion auto-pause. Drop-in geolocation for Strava-class apps.
Maintainers
Readme
react-native-fitness-geolocation
Production-grade React Native GPS for fitness and activity tracking apps — background location, native SQLite persistence, and optional motion auto-pause.
Drop-in replacement for @react-native-community/geolocation with extensions for Strava/Nike-class reliability.
npm install react-native-fitness-geolocation
cd ios && pod installPlatform support
| Feature | iOS | Android |
|---------|-----|---------|
| getCurrentPosition / watchPosition | ✅ | ✅ |
| Background GPS + SQLite queue | ✅ | ✅ |
| Built-in foreground tracking service | — | ✅ |
| Foreground queue replay | ✅ | ✅ |
| Watch restore after app restart | ✅ | ✅ |
| distanceFilter, interval, maximumAge | ✅ | ✅ |
| Motion auto-pause (MotionEngine) | ✅ | 🚧 scaffold |
| CLBackgroundActivitySession (iOS 17+) | ✅ | — |
Quick start
import Geolocation from 'react-native-fitness-geolocation';
// One-shot location (map pin, start screen)
Geolocation.getCurrentPosition(
position => console.log(position.coords),
error => console.warn(error),
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 },
);
// Continuous tracking (run / ride / hike)
const watchId = Geolocation.watchPosition(
position => saveRoutePoint(position),
error => console.warn(error),
{
enableHighAccuracy: true,
distanceFilter: 5,
interval: 3000,
fastestInterval: 1000,
showsBackgroundLocationIndicator: true, // iOS
},
);
// Stop
Geolocation.clearWatch(watchId);Permissions
Use built-in helpers or your own flow:
import { PermissionManager } from 'react-native-fitness-geolocation';
const result = await PermissionManager.requestFitnessPermissions({
includeMotion: true, // Android ACTIVITY_RECOGNITION
});
if (result.status !== 'ready') {
await PermissionManager.openSettings();
}Or configure once (community-geolocation compatible):
Geolocation.setRNConfiguration({
skipPermissionRequests: false,
authorizationLevel: 'always', // fitness apps
});Background tracking
GPS continues in the background. Points collected while JS is suspended are stored in native SQLite and replayed when the app returns to foreground — no data loss on lock screen.
// Manual sync (usually automatic via AppState)
const count = await Geolocation.syncPendingLocations();
console.log(`Delivered ${count} queued points`);Production lifecycle API
For workout recording, use the native-first lifecycle API. This gives the app a clear state machine: configure, subscribe, start native recording, sync the native SQLite queue, then stop.
import { BackgroundGeolocation } from 'react-native-fitness-geolocation';
const sub = BackgroundGeolocation.onLocation(
async location => {
await saveCoordinateToRealm(location);
},
error => console.warn(error),
);
await BackgroundGeolocation.ready({
authorizationLevel: 'always',
enableHighAccuracy: true,
desiredAccuracy: 10,
distanceFilter: 0,
locationUpdateInterval: 1000,
fastestLocationUpdateInterval: 1000,
trackingMode: 'fitness',
pausesLocationUpdatesAutomatically: false,
showsBackgroundLocationIndicator: true,
notificationTitle: 'Activity tracking active',
notificationText: 'Recording your route in the background',
});
await BackgroundGeolocation.start();
// End workout
await BackgroundGeolocation.sync();
await BackgroundGeolocation.stop();
sub.remove();For device testing, subscribe to native diagnostics:
const diagnosticSub = BackgroundGeolocation.onDiagnostic(event => {
console.log('[FitnessGeo]', event.event, event);
});
const history = await BackgroundGeolocation.getDiagnostics();Useful events include location-raw, location-drop, location-persist, persist-failed, watch-start, watch-stop, watch-restore, foreground, and authorization-change.
Required setup: See docs/SETUP.md for Info.plist and AndroidManifest snippets.
Verify your app:
npx react-native-fitness-geolocation verify-setupFitness apps (optional layer)
For full workout orchestration — permissions + GPS + motion + auto-pause:
import { createFitnessEngine } from 'react-native-fitness-geolocation';
const engine = createFitnessEngine({ autoPause: true, includePedometer: false });
await engine.prepare();
engine.start(
position => onLocation(position),
error => onError(error),
{ trackingMode: 'fitness' },
);
// Later
engine.stop();FitnessEngine is optional. Plain Geolocation.watchPosition works for any app.
Migration from @react-native-community/geolocation
- import Geolocation from '@react-native-community/geolocation';
+ import Geolocation from 'react-native-fitness-geolocation';Same API: getCurrentPosition, watchPosition, clearWatch, requestAuthorization, setRNConfiguration.
See docs/MIGRATION.md for options matrix and edge cases.
API reference
Geolocation (default export)
| Method | Description |
|--------|-------------|
| getCurrentPosition(success, error?, options?) | Single fix with timeout, maximumAge |
| watchPosition(success, error?, options?) → number | Continuous updates |
| clearWatch(id) | Stop one watch |
| stopObserving() | Stop all watches |
| requestAuthorization(level?) | 'whenInUse' | 'always' |
| getAuthorizationStatus() | { status, always } |
| setRNConfiguration(config) | Global config |
| syncPendingLocations() | Drain SQLite queue to callbacks |
| getQueueSize() | Pending point count |
| addAuthorizationListener(cb) | Permission change events |
Options (GeolocationOptions)
| Option | Default | Notes |
|--------|---------|-------|
| timeout | 15000 | ms, emits error code 3 |
| maximumAge | 0 | Accept cached fix if younger (ms) |
| enableHighAccuracy | true | |
| desiredAccuracy | — | native accuracy target in meters |
| distanceFilter | 5 | meters |
| distanceFilter: 0 | — | densest route recording; useful for Strava-style workouts |
| interval | 3000 | Android update interval (ms); iOS is distance/accuracy driven |
| locationUpdateInterval | — | alias for background-geolocation style Android configs |
| fastestInterval | 1000 | Android min interval (ms) |
| fastestLocationUpdateInterval | — | alias for background-geolocation style Android configs |
| trackingMode | — | fitness | navigation | balanced | low_power |
| enableMotion | false | Opt-in motion engine with watch |
Error codes (PositionError)
| Code | Constant | Meaning |
|------|----------|---------|
| 1 | PERMISSION_DENIED | User denied location |
| 2 | POSITION_UNAVAILABLE | GPS unavailable |
| 3 | TIMEOUT | Request timed out |
Android background note
For long sessions with the screen off, Android requires a foreground service with a persistent notification. This package now ships its own location foreground service, native GPS pipeline, and SQLite queue, so activity tracking does not depend on react-native-background-geolocation release builds.
For smooth workout polylines, prefer enableHighAccuracy: true, distanceFilter: 0 to 5, trackingMode: 'fitness', and pausesLocationUpdatesAutomatically: false. iOS does not guarantee exact 1-second background callbacks; the package records every accepted native fix and replays missed JS callbacks from SQLite.
Docs
| Doc | Description | |-----|-------------| | docs/SETUP.md | Platform permissions | | docs/MIGRATION.md | From community geolocation | | docs/PRODUCTION.md | Production checklist | | docs/PUBLISH.md | npm publish |
Requirements
- React Native ≥ 0.73
- iOS 13+ (iOS 17+ for background activity session)
- Android API 24+
- Bare workflow or Expo dev client (native module)
MIT · Arslan Khan
