npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@santoshpk/react-native-background-location-tracking

v0.1.0

Published

Continuous background & foreground location tracking for React Native (new arch / TurboModule)

Readme

react-native-background-location-tracking

Continuous foreground and background location tracking for React Native, built on the new architecture (TurboModule). A free, open-source alternative to the paid react-native-background-geolocation, with honest docs about the OS limits.

Capability matrix

Honesty first — this is what v1 actually does:

| Scenario | Android | iOS | Status | |----------|---------|-----|--------| | App foreground | ✅ continuous | ✅ continuous | v1 | | App backgrounded (process alive) | ✅ foreground service | ✅ background location mode | v1 | | App killed / swiped away | ⚠️ stops | ⚠️ stops | out of scope — future | | Device reboot | ⚠️ stops | ⚠️ stops | out of scope — future |

In scope v1: continuous tracking while the app process is alive — foreground and backgrounded, both platforms. Kill-state / reboot recovery (Android START_STICKY/BOOT_COMPLETED, iOS significant-location-change / geofencing) is not shipped and left to the user.

Installation

npm install @santoshpk/react-native-background-location-tracking

New architecture only. This library is a TurboModule and requires the React Native new architecture (default since RN 0.76). There is no old-architecture / bridge fallback, and none is planned — if you're on the legacy architecture, upgrade first.

Android setup

Permissions and the <service> entry are merged from the library manifest automatically. At runtime, requestPermissions() walks the required prompts in order:

  1. ACCESS_FINE_LOCATION
  2. POST_NOTIFICATIONS (Android 13+)
  3. ACCESS_BACKGROUND_LOCATION — user must pick "Allow all the time" (Android 10+)

Non-negotiable OS facts:

  • Android 14+ requires the location foreground-service type (already declared here).
  • The persistent notification cannot be hidden — it is required by the OS.

iOS setup

Add to Info.plist:

<key>NSLocationWhenInUseUsageDescription</key>
<string>Why you need location while the app is open.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Why you need location in the background.</string>
<key>UIBackgroundModes</key>
<array>
  <string>location</string>
</array>

Background tracking needs the user to grant "Always" authorization. The module sets allowsBackgroundLocationUpdates = true and pausesLocationUpdatesAutomatically = false.

Note: this library never fakes background execution with silent-audio/VoIP tricks — those get you rejected from the App Store.

Usage

import {
  requestPermissions,
  startTracking,
  stopTracking,
  getCurrentLocation,
  isTracking,
  onLocation,
  onError,
} from '@santoshpk/react-native-background-location-tracking';

// 1. Subscribe BEFORE starting, so you don't miss the first fixes.
//    `sub` is a subscription handle — keep it to unsubscribe later.
const sub = onLocation((loc) => {
  // Fires on every native update with fresh LocationData:
  console.log(loc.latitude, loc.longitude, loc.accuracy);
});
const errSub = onError((err) => console.warn(err.message));

// 2. Request permissions, then start.
// The rationale is optional — Android shows it when the user previously
// said no. On iOS your "why" lives in the Info.plist usage strings instead.
await requestPermissions({
  title: 'Location needed',
  message: 'MyApp uses your location to record your route.',
  buttonPositive: 'OK',
});
await startTracking({
  interval: 5000,          // ms (Android)
  fastestInterval: 5000,   // ms (Android)
  distanceFilter: 0,       // metres
  accuracy: 'high',        // 'high' | 'balanced' | 'low' | 'passive'
  notificationTitle: 'Tracking active',
  notificationText: 'Recording your location',
  notificationChannelName: 'Location tracking',
});

// One-shot helpers, independent of the stream:
const here = await getCurrentLocation(); // always resolves or rejects, never hangs
const active = await isTracking();

// 3. Cleanup — BOTH steps:
stopTracking(); // stops native GPS, the Android service + notification
sub.remove();   // detaches your JS listener (else it leaks and keeps firing)
errSub.remove();

How events flow

Native side emits, JS side listens — one-way:

startTracking(options)
  Android: FusedLocationProviderClient fires every `interval` ms
  iOS:     CLLocationManager fires on movement (distanceFilter throttles)
        ↓
  native emits the 'location' event
        ↓
  onLocation(callback) fires with LocationData

Cleanup is two independent levels — do both when you're done:

| Call | What it stops | |------|---------------| | sub.remove() | Your JS callback. Native keeps tracking. | | stopTracking() | Native GPS, foreground service, notification. |

In React, tie the listener to component lifetime:

useEffect(() => {
  const sub = onLocation(handleLocation);
  return () => sub.remove(); // unmount = unsubscribe
}, []);

Platform nuance: Android interval is timer-based — a fix every N ms even when stationary. iOS has no interval; CoreLocation is movement-driven, so a perfectly still device emits fewer events. Use distanceFilter to throttle iOS. OS design, not a bug.

API

| Function | Description | |----------|-------------| | requestPermissions(rationale?) | Request location (+ notification + background on Android). Optional rationale { title, message, buttonPositive } explains why — shown by Android when needed. Resolves true when foreground location granted (precise or approximate). iOS no-op — prompt fires on startTracking, reason text comes from Info.plist. | | startTracking(options?) | Start continuous tracking. Returns Promise<void>. | | stopTracking() | Stop tracking and the foreground service. | | getCurrentLocation() | One-shot fix. Returns Promise<LocationData>; rejects if unavailable. | | isTracking() | Returns Promise<boolean>. | | onLocation(cb) | Subscribe to updates. Returns a subscription — call .remove(). | | onError(cb) | Subscribe to warnings/errors. Returns a subscription. |

LocationData: { latitude, longitude, accuracy, altitude, speed, course, timestamp, fromMockProvider }.

Call requestPermissions() before startTracking(). On Android it walks the required runtime prompts in order (fine → notifications → background "Allow all the time"). On iOS the "Always" prompt fires when startTracking() runs. See example/src/App.tsx.

Security & privacy

What this package does — and deliberately doesn't do — with your users' location:

  • No network. No storage. Location data goes from the OS straight to your JS callback. Nothing is uploaded, cached, or written to disk by this library.
  • No location logging. Coordinates never appear in logcat / console output, so they can't leak through device logs.
  • Service is not exported. No other app can start, stop, or feed options into the tracking service.
  • Permission-guarded. startTracking() rejects with PERMISSION_DENIED if location permission is missing (also prevents the Android 14 foreground-service crash).
  • Spoof detection surface. Every fix carries fromMockProvider so you can flag faked locations yourself.
  • Input clamping. Malformed options (negative intervals etc.) are clamped natively instead of crashing the service.
  • No zombie tracking. If the React instance goes away, the Android service is stopped and the context reference released — no GPS burning with nobody listening, no leaked contexts.

Contributing

License

MIT


Made with create-react-native-library