License sales launch: April 27, 2026 Get notified or view pricing

bglocation

Documentation

Everything you need to integrate background location tracking into your React Native app. The native core stays the same. The wrapper and setup flow adapt to your stack.

Quick Install

npm install @bglocation/react-nativenpx expo prebuild

Expo projects should use the config plugin plus a dev client. Bare React Native apps still need cd ios && pod install after installation.

Getting Started

Install the React Native wrapper, configure tracking, and get your first location update in under 5 minutes.

1. Install

npm install @bglocation/react-native
npx expo prebuild

# Bare React Native
cd ios && pod install

2. Configure & Start

import {
  addListener,
  configure,
  start,
} from '@bglocation/react-native';

await configure({
  distanceFilter: 15,
  desiredAccuracy: 'high',
  heartbeatInterval: 15,
  locationUpdateInterval: 5000,
  debug: true,
});

const locationSubscription = addListener('onLocation', (location) => {
  console.log(location.latitude, location.longitude);
});

await start();

// later
locationSubscription.remove();

3. Stop Tracking

import { removeAllListeners, stop } from '@bglocation/react-native';

await stop();
removeAllListeners();

Permissions

The React Native wrapper uses the same permission model. Expo projects need a dev client and the config plugin. Bare React Native apps can request permissions through the exported requestPermissions() function after native setup is in place.

React Native support targets 0.76+ with the New Architecture and TurboModules.

Configuration

All options available in configure(). The React Native wrapper mirrors the same native config surface and merges partial updates.

Core Options

OptionTypeDefaultDescription
distanceFilternumber | 'auto'15Minimum distance in meters between updates, or 'auto' for speed-adaptive mode.
desiredAccuracy'high' | 'balanced' | 'low''high'Accuracy preset used by the native location manager.
heartbeatIntervalnumber15Heartbeat interval in seconds. Fires even when stationary.
locationUpdateIntervalnumber5000Android-only update interval in milliseconds.
fastestLocationUpdateIntervalnumber2000Android-only lower bound for high-frequency updates.
debugbooleanfalseEnables verbose logs and onDebug events.

HTTP Posting

Native HTTP delivery works the same in Capacitor and React Native. The JavaScript wrapper configures it once, then URLSession on iOS and HttpURLConnection on Android post directly from the native layer.

await configure({
  distanceFilter: 15,
  desiredAccuracy: 'high',
  heartbeatInterval: 15,
  locationUpdateInterval: 5000,
  fastestLocationUpdateInterval: 2000,
  http: {
    url: 'https://api.example.com/locations',
    headers: { Authorization: 'Bearer <token>' },
    buffer: { maxSize: 1000 },
  },
});

HTTP POST Body

{
  "location": {
    "latitude": 52.2297,
    "longitude": 21.0122,
    "accuracy": 5.0,
    "speed": 1.2,
    "heading": 180.0,
    "altitude": 110.5,
    "timestamp": 1700000000000,
    "isMoving": true,
    "isMock": false
  }
}

HttpEvent

interface HttpEvent {
  statusCode: number;
  success: boolean;
  responseText: string;
  error?: string;
  bufferedCount?: number;
}

Offline Buffer & Retry

Failed POSTs are stored in SQLite when buffer.maxSizeis configured. Buffered locations flush automatically in FIFO order after the next successful request.

Adaptive Distance Filter

Use auto mode to target stable update intervals regardless of whether the user is walking, cycling, or driving.

distanceFilter: 'auto',
autoDistanceFilter: {
  targetInterval: 10,
  minDistance: 10,
  maxDistance: 500,
}

Notification (Android)

Android tracking runs as a foreground service. Customize the persistent notification text from the wrapper.

notification: {
  title: 'Background Location',
  text: 'Tracking your route',
}

Partial Reconfiguration

Subsequent configure() calls merge with the last applied config. Pass only the fields you want to change.

API Reference

Complete TypeScript API exported by @bglocation/react-native.

Methods

MethodReturnsDescription
getVersion()Promise<VersionInfo>Get wrapper and native core version information.
checkPermissions()Promise<LocationPermissionStatus>Check current foreground and background permission state.
requestPermissions(options?)Promise<LocationPermissionStatus>Request foreground or background location permissions.
configure(options)Promise<ConfigureResult>Configure tracking before start(); partial updates are merged.
start()Promise<LocationState>Start background location tracking.
stop()Promise<LocationState>Stop background location tracking.
getState()Promise<LocationState>Read the current enabled/tracking state.
getCurrentPosition(options?)Promise<Location>Request a single location update.
addGeofence(geofence)Promise<void>Register one geofence region.
addGeofences({ geofences })Promise<void>Register multiple geofences atomically.
removeGeofence({ identifier })Promise<void>Remove a geofence by identifier.
removeAllGeofences()Promise<void>Clear all geofences.
getGeofences()Promise<{ geofences: Geofence[] }>Return the currently registered geofences.
checkBatteryOptimization()Promise<BatteryWarningEvent>Inspect Android battery optimization state.
requestBatteryOptimization()Promise<BatteryWarningEvent>Open Android battery optimization settings.
removeAllListeners()voidRemove all active event listeners registered through the wrapper.

Events

Register listeners via addListener(event, handler) and keep the returned Subscription so you can remove it later.

EventPayloadDescription
onLocationLocationLocation update based on distanceFilter.
onHeartbeatHeartbeatEventPeriodic heartbeat, even when stationary.
onProviderChangeProviderChangeEventGPS/network provider status changed.
onHttpHttpEventNative HTTP POST result.
onDebugDebugEventDebug log message when debug mode is enabled.
onBatteryWarningBatteryWarningEventBattery optimization warning on Android.
onAccuracyWarningAccuracyWarningEventApproximate location warning on iOS 14+.
onMockLocationMockLocationEventMock location detected on Android.
onPermissionRationalePermissionRationaleEventShow a custom rationale before background permission.
onTrialExpiredTrialExpiredEventTrial session ended and tracking stopped automatically.
onGeofenceGeofenceEventGeofence transition: enter, exit, or dwell.

Location Object

interface Location {
  latitude: number;
  longitude: number;
  accuracy: number;
  speed: number;
  heading: number;
  altitude: number;
  timestamp: number;
  isMoving: boolean;
  isMock: boolean;
  effectiveDistanceFilter?: number;
}

Geofencing

Geofencing is available through the same API surface in both wrappers. Up to 20 regions can be active at once.

interface Geofence {
  identifier: string;
  latitude: number;
  longitude: number;
  radius: number;
  notifyOnEntry?: boolean;
  notifyOnExit?: boolean;
  notifyOnDwell?: boolean;
  dwellDelay?: number;
  extras?: Record<string, string>;
}

GeofenceEvent Interface

interface GeofenceEvent {
  identifier: string;
  action: 'enter' | 'exit' | 'dwell';
  location: Location | null;
  extras?: Record<string, string>;
  timestamp: number;
}

Error Codes

CodeDescription
NOT_CONFIGUREDconfigure() must run before adding geofences.
GEOFENCE_LIMIT_EXCEEDEDThe wrapper enforces the 20 geofence limit.
GEOFENCE_ERRORNative registration failed.
UNSUPPORTEDThe current runtime does not support the attempted native operation.

Platform Guides

Platform-specific setup for iOS and Android. The native core is the same, but the wrapper decides how much gets automated for you.

iOS

Info.plist — Required Keys

Expo projects can generate these values through the config plugin. Bare React Native apps should add them directly in Info.plist.

<key>NSLocationWhenInUseUsageDescription</key>
<string>We need your location to track your route.</string>

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Background location is needed for continuous tracking.</string>

Background Modes

Enable Location updates in Xcode. Expo users get this automatically after expo prebuild when the config plugin is configured.

<key>UIBackgroundModes</key>
<array>
  <string>location</string>
</array>

Expo Config Plugin

The React Native package ships with an Expo config plugin that injects permissions, background modes, and the license key during prebuild.

{
  "expo": {
    "plugins": [
      [
        "@bglocation/react-native",
        {
          "licenseKey": "BGL1-eyJ...",
          "locationWhenInUsePermission": "We use your location to track your route.",
          "locationAlwaysPermission": "We use your location in the background for continuous tracking."
        }
      ]
    ]
  }
}

SLC Fallback

Significant Location Change monitoring is registered automatically. If iOS kills the app, the native core uses SLC to relaunch and resume standard GPS tracking.

Minimum Deployment Target

iOS 15.0+.

Android

Permissions

Expo prebuild or the Android manifest merger will add the required permissions from the React Native package.

ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_BACKGROUND_LOCATION
FOREGROUND_SERVICE
FOREGROUND_SERVICE_LOCATION
POST_NOTIFICATIONS

Foreground Service

Tracking runs inside a foreground service with a persistent notification. This is what keeps Android from killing the process during long sessions.

Battery Optimization

OEM battery killers are detected automatically. The wrapper emits onBatteryWarning with an OEM-specific help URL.

Two-Step Permission Flow

await requestPermissions({
  permissions: ['location'],
});

await requestPermissions({
  permissions: ['backgroundLocation'],
});

Minimum SDK

minSdk 26 (Android 8.0), compileSdk 36.

Licensing

Trial mode, offline validation, bundle ID binding, and where to place your license key.

Trial Mode

  • 30-minute sessions with automatic stop and an onTrialExpired event.
  • 1-hour cooldown between trial sessions.
  • Debug mode is forced on so you can inspect behavior before buying.

Adding a License Key

Expo users should configure the package plugin. Bare React Native apps can set the same value directly in native config.

{
  "expo": {
    "plugins": [
      [
        "@bglocation/react-native",
        {
          "licenseKey": "BGL1-eyJ..."
        }
      ]
    ]
  }
}
<!-- iOS Info.plist -->
<key>BGLocationLicenseKey</key>
<string>BGL1-eyJ...</string>

<!-- AndroidManifest.xml -->
<meta-data
  android:name="dev.bglocation.LICENSE_KEY"
  android:value="BGL1-eyJ..." />

How Validation Works

  • RSA-2048 signed payloads are verified fully offline on-device.
  • The license is bound to a bundle ID and can be used across the Capacitor and React Native wrappers for the same app identifier.
  • The license itself is perpetual. One year of updates is included, then update access can be renewed.

License Status

const result = await configure({ ... });

// result.licenseMode: 'full' | 'trial'
// result.licenseUpdatesUntil?: string
// result.licenseUpdateExpired?: boolean
// result.licenseError?: string

Examples

Real-world integration patterns for common production use cases.

Fleet / Delivery Tracking

Continuous tracking with native HTTP posting and automatic offline buffering.

import { addListener, configure, start } from '@bglocation/react-native';

await configure({
  distanceFilter: 'auto',
  autoDistanceFilter: {
    targetInterval: 10,
    minDistance: 10,
    maxDistance: 500,
  },
  desiredAccuracy: 'high',
  heartbeatInterval: 30,
  http: {
    url: 'https://api.fleet.com/vehicle/location',
    headers: { Authorization: 'Bearer <token>' },
    buffer: { maxSize: 2000 },
  },
});

addListener('onHttp', (event) => {
  if (!event.success) {
    console.warn('Buffered:', event.bufferedCount);
  }
});

await start();

Fitness / Running App

High-frequency tracking with in-memory processing for pace, route, and progress stats.

import {
  addListener,
  configure,
  start,
} from '@bglocation/react-native';
import type { Location } from '@bglocation/react-native';

const route: Location[] = [];

await configure({
  distanceFilter: 5,
  desiredAccuracy: 'high',
  heartbeatInterval: 10,
  locationUpdateInterval: 3000,
});

addListener('onLocation', (location) => {
  route.push(location);
  updateMapPolyline(route);
});

await start();

Geofencing — Points of Interest

Register circular regions and react to enter, exit, and dwell transitions.

import {
  addGeofence,
  addListener,
  configure,
  start,
} from '@bglocation/react-native';

await configure({
  distanceFilter: 50,
  desiredAccuracy: 'balanced',
  heartbeatInterval: 60,
});

await addGeofence({
  identifier: 'office',
  latitude: 52.2297,
  longitude: 21.0122,
  radius: 100,
  notifyOnEntry: true,
  notifyOnExit: true,
});

addListener('onGeofence', (event) => {
  console.log(event.identifier, event.action);
});

await start();