Skip to content
 
 

Repository files navigation

Background Geolocation

Capgo - Instant updates for capacitor

A Capacitor plugin that lets you receive accurate geolocation updates even while the app is backgrounded. It has a web API to facilitate for a similar usage, but background geolocation is not supported in a regular browser, only in an app environment.

This plugin's history

Interestingly enough, this plugin has a lot of history. The initial solution from Transistorsoft was a great piece of software, and I (HarelM) encourage using it if it fits your needs.
I tried it and understood that it prioritizes battery life over accuracy, which wasn't the right fit for my hiking app.
There was a very good fork maintained by mauron85 specifically for that use case, and I was happy to help maintain it.
But at some point, mauron85 stopped responding to messages on GitHub, and no one could continue maintaining it.
I hope mauron85 is safe and sound somewhere.

So I created a fork and started maintaining it here.
It served me well for over half a decade, but I felt it was hard to maintain due to all its history, features, and bug fixes.
I also felt like there was a barrier to introducing new features because of its complexity.

So I started exploring what it would take to reduce that complexity—at the same time, I was envious of how small @capacitor-community/background-geolocation is.
I took the best of both worlds: tried to reduce the codebase in the original Cordova plugin and add some robustness to the Capacitor plugin.

That's how I ended up maintaining this one.
I hope you'll enjoy it!

Plugin comparison

A short comparison between the three main background-geolocation plugins commonly used in Capacitor apps.

Plugin Accuracy Background HTTP Upload Pricing
@capacitor-community/background-geolocation (Community) Not accurate Yes No Free
@capgo/background-geolocation (this plugin) Accurate Yes No Free
Transistorsoft (original) Accurate Yes Yes — built-in HTTP uploader to your API Paid

Notes:

  • The Community plugin is lightweight and continues to work in the background, but it is known to be less accurate than the options below.
  • This Cap-go plugin aims to provide accurate location fixes and reliable background operation without requiring a paid license.
  • Transistorsoft's plugin is a mature, accurate solution that also includes an HTTP uploader (it can send location updates to your API). It is a commercial product and requires a paid license for full use.

Usage

import { BackgroundGeolocation } from "@capgo/background-geolocation";

BackgroundGeolocation.start(
    {
        backgroundMessage: "Cancel to prevent battery drain.",
        backgroundTitle: "Tracking You.",
        requestPermissions: true,
        stale: false,
        distanceFilter: 50
    },
    (location, error) => {
        if (error) {
            if (error.code === "NOT_AUTHORIZED") {
                if (window.confirm(
                    "This app needs your location, " +
                    "but does not have permission.\n\n" +
                    "Open settings now?"
                )) {
                    // It can be useful to direct the user to their device's
                    // settings when location permissions have been denied. The
                    // plugin provides the 'openSettings' method to do exactly
                    // this.
                    BackgroundGeolocation.openSettings();
                }
            }
            return console.error(error);
        }
        return console.log(location);
    }
).then(() => {
    // When location updates are no longer needed, the plugin should be stopped by calling
    BackgroundGeolocation.stop();
});

// Set a planned route to get a notification sound when a new location arrives and it's not on the route:
        
BackgroundGeolocation.setPlannedRoute({soundFile: "assets/myFile.mp3", route: [[1,2], [3,4]], distance: 30 });

// If you just want the current location, try something like this. The longer
// the timeout, the more accurate the guess will be. I wouldn't go below about 100ms.
function guessLocation(callback, timeout) {
    let last_location;
    BackgroundGeolocation.start(
        {
            requestPermissions: false,
            stale: true
        },
        (location) => {
            last_location = location || undefined;
        }
    ).then(() => {
        setTimeout(() => {
            callback(last_location);
            BackgroundGeolocation.stop();
        }, timeout);
    });
}

Documentation

The most complete doc is available here: https://capgo.app/docs/plugins/background-geolocation/

Compatibility

Plugin version Capacitor compatibility Maintained
v8.*.* v8.*.*
v7.*.* v7.*.* On demand
v6.*.* v6.*.*
v5.*.* v5.*.*

Note: The major version of this plugin follows the major version of Capacitor. Use the version that matches your Capacitor installation (e.g., plugin v8 for Capacitor 8). Only the latest major version is actively maintained.

Installation

This plugin supports Capacitor v7:

Capacitor Plugin
v7 v7
npm install @capgo/background-geolocation
npx cap update

iOS

Add the following keys to Info.plist.:

<dict>
  ...
  <key>NSLocationWhenInUseUsageDescription</key>
  <string>We need to track your location</string>
  <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
  <string>We need to track your location while your device is locked.</string>
  <key>UIBackgroundModes</key>
  <array>
    <string>location</string>
  </array>
  ...
</dict>

Android

Set the the android.useLegacyBridge option to true in your Capacitor configuration. This prevents location updates halting after 5 minutes in the background. See https://capacitorjs.com/docs/config and capacitor-community/background-geolocation#89.

On Android 13+, the app needs the POST_NOTIFICATIONS runtime permission to show the persistent notification informing the user that their location is being used in the background. This runtime permission is requested after the location permission is granted.

If your app forwards location updates to a server in real time, be aware that after 5 minutes in the background Android will throttle HTTP requests initiated from the WebView. The solution is to use a native HTTP plugin such as CapacitorHttp. See capacitor-community/background-geolocation#14.

Configuration specific to Android can be made in strings.xml:

<resources>
    <!--
        The channel name for the background notification. This will be visible
        when the user presses & holds the notification. It defaults to
        "Background Tracking".
    -->
    <string name="capacitor_background_geolocation_notification_channel_name">
        Background Tracking
    </string>

    <!--
        The icon to use for the background notification. Note the absence of a
        leading "@". It defaults to "mipmap/ic_launcher", the app's launch icon.

        If a raster image is used to generate the icon (as opposed to a vector
        image), it must have a transparent background. To make sure your image
        is compatible, select "Notification Icons" as the Icon Type when
        creating the image asset in Android Studio.

        An incompatible image asset will cause the notification to misbehave in
        a few telling ways, even if the icon appears correctly:

          - The notification may be dismissable by the user when it should not
            be.
          - Tapping the notification may open the settings, not the app.
          - The notification text may be incorrect.
    -->
    <string name="capacitor_background_geolocation_notification_icon">
        drawable/ic_tracking
    </string>

    <!--
        The color of the notification as a string parseable by
        android.graphics.Color.parseColor. Optional.
    -->
    <string name="capacitor_background_geolocation_notification_color">
        yellow
    </string>
</resources>

API

Main plugin interface for background geolocation functionality.

start(...)

start(options: StartOptions, callback: (position?: Location | undefined, error?: CallbackError | undefined) => void) => Promise<void>

Start listening for location changes. The callback is invoked each time a new location is available.

Param Type
options StartOptions
callback (position?: Location, error?: CallbackError) => void

Since: 7.0.9


stop()

stop() => Promise<void>

Stop location updates and the background service.

Since: 7.0.9


openSettings()

openSettings() => Promise<void>

Opens the device's location settings page.

Since: 7.0.0


setPlannedRoute(...)

setPlannedRoute(options: SetPlannedRouteOptions) => Promise<void>

Set a planned route with audio alert on deviation.

Param Type
options SetPlannedRouteOptions

Since: 7.0.11


getPluginVersion()

getPluginVersion() => Promise<{ version: string; }>

Get the native Capacitor plugin version.

Returns: Promise<{ version: string; }>


configure(...)

configure(config: HeadlessConfig) => Promise<void>

Configure headless mode for native HTTP posting of location batches to a server endpoint. Call this before start() or whenever the auth token needs refreshing.

Param Type
config HeadlessConfig

Since: 1.0.0


getBufferedLocations()

getBufferedLocations() => Promise<{ locations: BufferedLocation[]; }>

Get all locations buffered locally on the device.

Returns: Promise<{ locations: BufferedLocation[]; }>

Since: 1.0.0


clearBufferedLocations()

clearBufferedLocations() => Promise<void>

Clear all locally buffered locations.

Since: 1.0.0


getAuthorizationStatus()

getAuthorizationStatus() => Promise<{ status: 'notDetermined' | 'whenInUse' | 'always' | 'denied' | 'restricted'; }>

Get the current native location authorization status.

  • notDetermined — user has never been asked (iOS) or permission hasn't been requested (Android)
  • whenInUse — user allowed location only while using the app (iOS) / foreground only (Android)
  • always — user allowed location all the time (iOS) / background granted (Android)
  • denied — user denied location access
  • restricted — location is restricted by parental controls or MDM (iOS only)

Use this to detect whether to show an in-app prompt asking the user to upgrade from "While Using" to "Always" via Settings.

Returns: Promise<{ status: 'notDetermined' | 'whenInUse' | 'always' | 'denied' | 'restricted'; }>

Since: 1.0.0


Interfaces

StartOptions

The options for configuring for location updates.

Prop Type Description Default Since
backgroundMessage string If the "backgroundMessage" option is defined, the plugin will provide location updates whether the app is in the background or the foreground. If it is not defined, location updates are only guaranteed in the foreground. This is true on both platforms. On Android, a notification must be shown to continue receiving location updates in the background. This option specifies the text of that notification. 7.0.9
backgroundTitle string The title of the notification mentioned above. "Using your location" 7.0.9
requestPermissions boolean Whether permissions should be requested from the user automatically, if they are not already granted. true 7.0.9
stale boolean If "true", stale locations may be delivered while the device obtains a GPS fix. You are responsible for checking the "time" property. If "false", locations are guaranteed to be up to date. false 7.0.9
distanceFilter number The distance in meters that the device must move before a new location update is triggered. 0 7.0.9
stopOnTerminate boolean If false, the service will continue running after the app is terminated. false 1.0.0
startOnBoot boolean If true, the service will restart after a device reboot if it was running before the reboot. true 1.0.0
maxTrackingDurationMs number Maximum tracking duration in milliseconds. The service will auto-stop after this duration to prevent indefinite battery drain if the user forgets to check out. 43200000 (12 hours) 1.0.0

Location

Represents a geographical location with various attributes.

Prop Type Description Since
latitude number Latitude in degrees. Range: -90.0 to +90.0 7.0.0
longitude number Longitude in degrees. Range: -180.0 to +180.0 7.0.0
accuracy number Radius of horizontal uncertainty in metres, with 68% confidence. 7.0.0
altitude number | null Metres above sea level (or null if not available). 7.0.0
altitudeAccuracy number | null Vertical uncertainty in metres, with 68% confidence (or null if not available). 7.0.0
simulated boolean true if the location was simulated by software, rather than GPS. 7.0.0
bearing number | null Deviation from true north in degrees (or null if not available). 7.0.0
speed number | null Speed in metres per second (or null if not available). 7.0.0
time number | null Time the location was produced, in milliseconds since the unix epoch. 7.0.0

CallbackError

Error object that may be passed to the location start callback.

Prop Type Description Since
code string Optional error code for more specific error handling. 7.0.0

SetPlannedRouteOptions

Prop Type Description Default Since
soundFile string The name of the sound file to play. Must be a valid sound relative path in the app's public folder. 7.0.10
route [number, number][] The planned route as an array of longitude and latitude pairs. 7.0.11
distance number The distance in meters to deviate before triggering the sound. 50 7.0.11

HeadlessConfig

Configuration for headless mode — native HTTP posting of location batches to a server endpoint without the WebView being alive.

Prop Type Description Default Since
serverUrl string The server URL to POST location batches to. 1.0.0
authToken string JWT Bearer token for authentication. 1.0.0
employeeId string Employee identifier included in the POST payload. 1.0.0
tenantId string Tenant identifier included in the POST payload. 1.0.0
headers Record<string, string> Additional HTTP headers to include in the POST request. 1.0.0
batchSize number Number of locations to include in each batch POST. 20 1.0.0
postIntervalMs number Interval in milliseconds between batch POST attempts. 60000 1.0.0

BufferedLocation

A buffered location record stored locally on the device.

Prop Type
lat number
lng number
accuracy number
speed number
bearing number
altitude number
timestamp number

Type Aliases

Record

Construct a type with a set of properties K of type T

{ [P in K]: T; }

About

Capacitor plugin that sends you accurate geolocation updates, even while the app is in the background.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages