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

@gabriel-sisjr/react-native-background-location

v0.12.0

Published

React Native library for background location tracking using TurboModules. Track user location even when the app is minimized or in the background.

Readme

@gabriel-sisjr/react-native-background-location

NPM Version NPM Beta NPM Downloads NPM Total Downloads CI Tests Code Coverage Pre-release CI Release CI GitHub Stars License Bundlephobia Platform Android Platform iOS TypeScript

A cross-platform React Native library for background location tracking built on TurboModules (New Architecture). Tracks user location reliably on both Android and iOS even when the app is minimized, with persistent storage, crash recovery, and platform-native behavior.

Tracking demo

Table of Contents

Features

  • Cross-platform background location tracking (Android and iOS)
  • Real-time event-driven location updates on both platforms
  • Crash recovery with automatic session restoration (WorkManager on Android, significant location monitoring on iOS)
  • Configurable accuracy levels and update intervals for battery efficiency
  • Distance filtering and callback throttling
  • Session-based tracking organized by trip IDs
  • Persistent storage: Room Database (Android) / Core Data (iOS)
  • Full notification customization on Android: icons, colors, action buttons, dynamic updates
  • Static notification defaults via AndroidManifest or convention drawables (Android)
  • Android 14/15 compliance (foreground service type, timeout handling)
  • Provider abstraction with Google Play Services primary and fallback provider (Android)
  • CLLocationManager with WhenInUse and Always authorization levels (iOS)
  • Foreground-only mode (no background permission required)
  • Fully typed TypeScript API with unified cross-platform hooks

Installation

npm install @gabriel-sisjr/react-native-background-location
# or
yarn add @gabriel-sisjr/react-native-background-location

Android Setup

Add the required permissions to android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
</manifest>

On Android 11+, background location must be requested separately from foreground permissions. See the Quick Start Guide for the full permission flow and the Integration Guide for detailed setup in existing apps.

iOS Setup

  1. Add the following keys to your Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>We need your location to track your trips.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We need your location in the background to continue tracking your trips.</string>
  1. Enable the Location updates Background Mode in your Xcode project under Signing & Capabilities.

  2. Run pod install in your ios/ directory.

iOS: Unlike Android, iOS does not use a foreground notification for background tracking. Instead, the system shows a blue status bar indicator when the app is using location in the background. See the iOS Setup Guide for full details and App Store compliance requirements.

Quick Start

import {
  useLocationPermissions,
  useBackgroundLocation,
  useLocationUpdates,
  LocationAccuracy,
} from '@gabriel-sisjr/react-native-background-location';

function TrackingScreen() {
  const { permissionStatus, requestPermissions } = useLocationPermissions();
  const { startTracking, stopTracking, isTracking } = useBackgroundLocation();
  const { locations, lastLocation } = useLocationUpdates({
    onLocationUpdate: (loc) => console.log('New:', loc.latitude, loc.longitude),
  });

  if (!permissionStatus.hasAllPermissions) {
    return <Button title="Grant Permissions" onPress={requestPermissions} />;
  }

  return (
    <View>
      <Text>Status: {isTracking ? 'Tracking' : 'Stopped'}</Text>
      <Text>Points: {locations.length}</Text>
      {lastLocation && <Text>Last: {lastLocation.latitude}, {lastLocation.longitude}</Text>}
      <Button
        title={isTracking ? 'Stop' : 'Start'}
        onPress={() => isTracking
          ? stopTracking()
          : startTracking(undefined, { accuracy: LocationAccuracy.HIGH_ACCURACY })
        }
      />
    </View>
  );
}

For step-by-step setup, see the Quick Start Guide. For the direct (non-hook) API, see Using Direct API.

Hooks

| Hook | Purpose | | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | useLocationPermissions | Manages cross-platform permission flow (Android: foreground, background, notifications; iOS: WhenInUse, Always, notifications) | | useBackgroundLocation | Full tracking control: start, stop, locations, trip management | | useLocationTracking | Lightweight tracking status monitor (read-only) | | useLocationUpdates | Real-time event-driven location stream with warnings and action callbacks |

See the Hooks Guide for complete documentation, options, and examples.

API Reference

Methods

| Method | Signature | Description | | -------------------- | ----------------------------------------------------------------- | ---------------------------------------------------- | | startTracking | (options?: TrackingOptions) => Promise<string> | Start tracking (auto-generates trip ID) | | startTracking | (tripId?: string, options?: TrackingOptions) => Promise<string> | Start or resume tracking with a specific trip ID | | stopTracking | () => Promise<void> | Stop tracking and terminate the background service | | isTracking | () => Promise<TrackingStatus> | Check if tracking is active | | getLocations | (tripId: string) => Promise<Coords[]> | Retrieve all stored locations for a trip | | clearTrip | (tripId: string) => Promise<void> | Delete all stored data for a trip | | updateNotification | (title: string, text: string) => Promise<void> | Update notification content while tracking is active |

TrackingOptions

All fields are optional. Defaults are applied when omitted.

| Field | Type | Default | Description | | ------------------------- | --------------------- | --------------- | ------------------------------------------------------------------------------------------------------- | | updateInterval | number | 5000 | Interval between location updates (ms) | | fastestInterval | number | 3000 | Fastest allowed update interval (ms) | | maxWaitTime | number | 10000 | Max wait before delivering batched updates (ms) | | accuracy | LocationAccuracy | HIGH_ACCURACY | Location accuracy priority | | waitForAccurateLocation | boolean | false | Delay updates until accurate location is available | | distanceFilter | number | 0 | Minimum distance (meters) between updates. 0 = no filter | | foregroundOnly | boolean | false | Track only while app is visible (no background permission needed) | | onUpdateInterval | number | undefined | Throttle callback execution (ms). Locations still collected at updateInterval | | notificationOptions | NotificationOptions | see below | Notification configuration for the foreground service. See NotificationOptions. |

NotificationOptions

All fields are optional. These configure the Android foreground service notification. On iOS, notification fields are silently ignored.

| Field | Type | Default | Description | | --------------- | ---------------------- | ---------------------------------------- | ---------------------------------------------------- | | title | string | "Location Tracking" | Notification title | | text | string | "Tracking your location in background" | Notification body text | | channelName | string | "Background Location" | Android notification channel name | | channelId | string | "background_location_channel" | Custom notification channel ID | | priority | NotificationPriority | LOW | Notification priority | | smallIcon | string | system default | Drawable resource name for small icon | | largeIcon | string | undefined | Drawable resource name for large icon | | color | string | undefined | Hex color for notification accent (e.g. "#FF5722") | | showTimestamp | boolean | false | Show timestamp on notification | | subtext | string | undefined | Subtext below notification content | | actions | NotificationAction[] | undefined | Up to 3 action buttons on the notification |

Types

Coords

interface Coords {
  latitude: string;
  longitude: string;
  timestamp: number;
  accuracy?: number;
  altitude?: number;
  speed?: number;
  bearing?: number;
  verticalAccuracyMeters?: number;
  speedAccuracyMetersPerSecond?: number;
  bearingAccuracyDegrees?: number;
  elapsedRealtimeNanos?: number;
  provider?: string;
  isFromMockProvider?: boolean;
}

Note: latitude and longitude are strings to preserve full decimal precision. Parse with parseFloat() when using with map libraries.

TrackingStatus

interface TrackingStatus {
  active: boolean;
  tripId?: string;
}

LocationUpdateEvent

interface LocationUpdateEvent {
  tripId: string;
  latitude: string;
  longitude: string;
  timestamp: number;
  accuracy?: number;
  altitude?: number;
  speed?: number;
  bearing?: number;
  verticalAccuracyMeters?: number;
  speedAccuracyMetersPerSecond?: number;
  bearingAccuracyDegrees?: number;
  elapsedRealtimeNanos?: number;
  provider?: string;
  isFromMockProvider?: boolean;
}

LocationWarningEvent and LocationWarningType

type LocationWarningType =
  | 'SERVICE_TIMEOUT'
  | 'TASK_REMOVED'
  | 'LOCATION_UNAVAILABLE';

interface LocationWarningEvent {
  tripId: string;
  type: LocationWarningType;
  message: string;
  timestamp: number;
}

NotificationAction and NotificationActionEvent

interface NotificationAction {
  id: string;
  label: string;
}

interface NotificationActionEvent {
  tripId: string;
  actionId: string;
}

LocationPermissionState

interface LocationPermissionState {
  hasPermission: boolean;
  status: LocationPermissionStatus;
  canRequestAgain: boolean;
}

NotificationPermissionState

interface NotificationPermissionState {
  hasPermission: boolean;
  status: NotificationPermissionStatus;
  canRequestAgain: boolean;
}

PermissionState

interface PermissionState {
  hasAllPermissions: boolean;
  location: LocationPermissionState;
  notification: NotificationPermissionState;
}

hasAllPermissions is true only when both location and notification permissions are granted. Individual permission states are accessible via the location and notification sub-objects.

UseLocationPermissionsResult

interface UseLocationPermissionsResult {
  permissionStatus: PermissionState;
  requestPermissions: () => Promise<boolean>;
  checkPermissions: () => Promise<boolean>;
  isRequesting: boolean;
}

UseBackgroundLocationResult

interface UseBackgroundLocationResult {
  tripId: string | null;
  isTracking: boolean;
  locations: Coords[];
  isLoading: boolean;
  error: Error | null;
  startTracking: (
    customTripId?: string,
    options?: TrackingOptions
  ) => Promise<string | null>;
  stopTracking: () => Promise<void>;
  refreshLocations: () => Promise<void>;
  clearCurrentTrip: () => Promise<void>;
  clearError: () => void;
}

UseLocationTrackingOptions

interface UseLocationTrackingOptions {
  autoStart?: boolean;
  tripId?: string;
  options?: TrackingOptions;
  onTrackingStart?: (tripId: string) => void;
  onTrackingStop?: () => void;
  onError?: (error: Error) => void;
}

UseLocationTrackingResult

interface UseLocationTrackingResult {
  isTracking: boolean;
  tripId: string | null;
  refresh: () => Promise<void>;
  isLoading: boolean;
}

UseLocationUpdatesOptions

interface UseLocationUpdatesOptions {
  tripId?: string;
  onLocationUpdate?: (location: Coords) => void;
  onUpdateInterval?: number;
  onLocationWarning?: (warning: LocationWarningEvent) => void;
  onNotificationAction?: (event: NotificationActionEvent) => void;
  autoLoad?: boolean;
}

UseLocationUpdatesResult

interface UseLocationUpdatesResult {
  tripId: string | null;
  isTracking: boolean;
  locations: Coords[];
  lastLocation: Coords | null;
  lastWarning: LocationWarningEvent | null;
  isLoading: boolean;
  error: Error | null;
  clearError: () => void;
  clearLocations: () => Promise<void>;
}

Enums

LocationAccuracy

| Value | Description | | ------------------------- | ----------------------------------------------------- | | HIGH_ACCURACY | GPS + sensors. Best accuracy, highest battery usage. | | BALANCED_POWER_ACCURACY | Balanced accuracy and power consumption. | | LOW_POWER | Network-based. Lower accuracy, better battery. | | NO_POWER | Only receives updates requested by other apps. | | PASSIVE | Passive updates from other apps. No additional power. |

NotificationPriority

| Value | Description | | --------- | ------------------------------- | | LOW | Minimal notification (default). | | DEFAULT | Default system priority. | | HIGH | More prominent notification. | | MAX | Urgent notification. |

LocationPermissionStatus

| Value | Description | | -------------- | -------------------------------------------------------------------------------- | | GRANTED | All required permissions granted (full background access). | | WHEN_IN_USE | iOS only: WhenInUse permission granted. Tracking works but may have limitations. | | DENIED | Permission denied (can request again). | | BLOCKED | Permission permanently denied (must open settings). | | UNDETERMINED | Permission not yet requested. |

NotificationPermissionStatus

| Value | Description | | -------------- | -------------------------------------- | | GRANTED | Notification permission granted. | | DENIED | Notification permission denied. | | UNDETERMINED | Notification permission not yet asked. |

Notification Customization

The foreground service notification supports full visual customization through the notificationOptions field on TrackingOptions (see NotificationOptions table above).

Static defaults can be configured without runtime code using AndroidManifest metadata or convention-named drawables:

<!-- AndroidManifest.xml -->
<meta-data android:name="com.backgroundlocation.default_notification_icon"
           android:resource="@drawable/ic_notification" />
<meta-data android:name="com.backgroundlocation.default_notification_color"
           android:resource="@color/notification_accent" />

Alternatively, place a drawable named bg_location_notification_icon in res/drawable/ for automatic detection.

Resolution priority: Runtime options > AndroidManifest metadata > Convention drawable > System default.

Dynamic updates allow changing notification text while tracking is active:

await BackgroundLocation.updateNotification(
  'Delivery #1234',
  'Arriving in 5 minutes'
);

Action buttons (max 3) can be added via notificationOptions.actions and handled through the onNotificationAction callback in useLocationUpdates.

Documentation

Getting Started

Production

Development

Platform Support

| Platform | Status | Notes | | -------- | --------- | ------------------------------------------------------------------- | | Android | Supported | Kotlin native implementation. Min SDK 24, target SDK 34. | | iOS | Supported | Swift native implementation. CLLocationManager, Core Data, iOS 13+. |

iOS: Background tracking on iOS uses the system blue status bar indicator instead of a notification. The notificationOptions field in TrackingOptions is Android-only and is silently ignored on iOS. See Platform Comparison for detailed differences.

Contributing

Contributions are welcome. See the Contributing Guide for development workflow, coding standards, and how to submit pull requests.

License

MIT