Library / SDK
transistorsoft/react-native-background-geolocation avatar
transistorsoft/react-native-background-geolocation

The source is MIT and a licence key is required to ship, and the Expo docs link to the React Native ones

Sophisticated, battery-conscious background-geolocation with motion-detection

2,935 stars446 forksTypeScriptMIT

At a glance

What is it?
A commercial background location and geofencing SDK for React Native and Expo, published as source with native iOS and Android code in tree. Its build script compiles one thing, its Expo documentation section repeats the React Native links, and there are no GitHub releases.
Who is it for?
Fit this if your application genuinely needs location while it is in the background and you are willing to pay for it at release time, because the battery argument only pays off if you are sampling continuously rather than on a timer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The source is MIT and the binary needs a key

Two licensing statements sit next to each other in this project, and they are about different things.

The package manifest declares the MIT licence, and the last line of the README says the project is MIT licensed and attributes it to a company. That is the licence on the source.

The licensing section of the README is about running it. A licence is required for release builds on both platforms. Debug builds are fully functional with no licence at all, described as a way to try before buying. To test a release build you can generate a free thirty day trial licence.

There is also a version boundary inside licensing. A callout states that the current line is the fifth major version, that the previous version is kept on a branch named for its own last release, and that licence keys issued for that version do not work with this one. The remedy is given as logging in to a customer dashboard to generate a key for the current version, and a migration guide is linked.

So the practical arrangement is a permissively licensed source tree with a key checked at build time for release builds. That is a licensing model rather than an open source one, and the README is explicit about it rather than burying it.

The Expo documentation section repeats the React Native links

The documentation section is two subsections long, and one of them is a copy.

The first subsection is for React Native and lists three links: setup, an API reference, and an example application. The second subsection is for Expo and lists three links as well, with the same three labels.

Every URL in the second subsection points at the same three paths as the first. They all sit under a React Native documentation prefix rather than an Expo one. So a reader who follows the Expo section lands on the React Native setup instructions three times.

That is a small documentation defect and it is worth naming because it sits in one of the three sections the README has, and because the project does support Expo: the package table below lists both React Native and Expo as served by this repository, the tree carries an Expo directory and a plugin entry point at its root, and the build script exists specifically to compile that plugin.

So the capability is real and the pointer to it is wrong. The likely path for the reader who notices is the example applications directory, which the README does link and which the tree confirms contains at least two example applications.

The build script compiles the Expo plugin and nothing else

Read the scripts in the manifest and the publishing model becomes clear.

There is one build script, and it delegates to another. The one it delegates to removes the Expo plugin's build directory and compiles that plugin with the TypeScript compiler in build mode.

json
"build:expo": "rimraf expo/plugin/build && tsc --build ./expo/plugin",

The script that runs before publishing is the build script. So publishing this package compiles the Expo plugin and does nothing else, which only makes sense because of the field beside it: the manifest's entry point for the library points at a file inside the source directory.

In other words, the JavaScript library ships as source and is compiled by the consuming application's build, and the only compiled artifact this package produces is the Expo configuration plugin. The native code is likewise shipped rather than built, with an iOS directory containing a podspec at the root and an Android directory beside it.

That is a deliberate trade: consumers of a React Native library already run a bundler, so shipping source saves a build step, and the Expo plugin is the exception because config plugins have to be compiled before the app tooling reads them.

The manifest also carries a code generation configuration, which names the module, declares its type, points at a specs directory inside the source tree as the input, and gives the Java package name for Android along with the module and package names for the Swift side.

Two test directories and two kinds of check in one command

The test script runs two different things, and the repository has two test directories to match.

One is a JavaScript test runner. The other is the TypeScript compiler pointed at a separate project directory, in a mode that checks types without emitting output. Both run under one command, chained so the second only runs if the first passes.

So there is a runtime suite and a type level suite, and they are distinguished by directory rather than by flag. The tree has a directory for each, plus a mocks directory and a test runner configuration file at the root.

That arrangement is what you would expect from a library whose main deliverable is a typed interface: the type level tests exist because a large share of the bugs in a native module surface as a wrong type on one platform rather than as a runtime error, and a type check across both platform definitions catches them without a device.

The rest of the task surface is small. There is a documentation generator run by a Node script and a separate script that publishes it, a preflight shell script, and a release shell script, alongside a releasing document at the root.

One more detail about the repository's release mechanics: it publishes no GitHub releases at all, so the version in the manifest is the only version a reader can find there.

The battery argument is a two state machine driven by three sensors

The feature that distinguishes this SDK from a periodic location request is stated in four lines, and the mechanism is a state machine rather than a schedule.

The system reads motion from three sources, named as the accelerometer, the gyroscope and the magnetometer. From those it decides whether the device is moving or stationary. There are exactly two named states and each has a defined consequence.

When moving, location recording starts automatically at a configured distance filter, expressed in metres. So the sampling interval is a distance, not a time, which means walking slowly and standing still produce different amounts of work.

When stationary, location services turn off automatically, and the stated reason is to conserve battery.

The product description and the README both call this the most sophisticated option available, and the manifest's description adds that it is cross platform while the README names iOS and Android. The comparison is with what, precisely, is not stated anywhere in either.

What is worth knowing before you rely on it is the failure shape. Both decisions are automatic, so a device that is genuinely moving but whose sensors report stillness, which happens with a stationary vehicle at a light, will have location services switched off under it. Nothing in the documentation describes an override or a way to force the moving state.

Six platforms are served by five repositories

The availability table is the most informative part of a short README, because it shows what this repository is responsible for and what it is not.

Two rows point at this repository: React Native and Expo. So this tree carries the JavaScript interface, the native iOS and Android sources, and the Expo configuration plugin.

Three rows point elsewhere. Flutter has its own repository and package name. Capacitor has its own repository and a scoped package name. Cordova has its own repository, and its package name carries a suffix that the others do not, which suggests it is a later or differently licensed addition to the family.

The last two rows are the interesting ones. Swift for iOS and Kotlin for Android both name the same repository, a native package, under the same package name. So one native repository serves both mobile platforms, and this repository consumes it and adds the React Native bridge on top.

Read as a whole, the family has one native core with several wrappers, and this repository is the wrapper for the two frameworks that need compiled native code shipped inside them. Anyone evaluating cost or maintenance is really choosing between six products that share a core, and the table is the only place that distinction is made.

The manifest compiles with Babel 8 and runs on Babel 7 helpers

Two dependency versions in this project are worth reading together rather than separately.

The runtime dependency on the Babel runtime helpers is on the seventh major line. The development dependencies on the compiler core and its preset environment are on the eighth major line, both with caret ranges.

So the package's own build pipeline compiles with one major version of the compiler while the helpers it emits calls into are taken from the previous major. That is not automatically wrong, since the two have separate version lines, but it is the kind of combination that is deliberate or that is a leftover, and nothing in the manifest or the README says which.

The dependency list is otherwise short and explains what the package needs at runtime: the Babel helpers, a small library of shared TypeScript helpers, and a separate published package holding the type definitions. That third one is the notable entry: the types for this SDK live in their own package on their own version line, so a consumer can pin types separately from the implementation.

The rest of the manifest is ordinary. An author, an issue tracker, a homepage that points at a store product page rather than at the repository, a keyword list, and a commit message hook configuration in the root.

A registry configuration file and an ignore file are both committed at the top level, which means the published file list is decided by an ignore file rather than by a list of inclusions in the manifest.

Editorial conclusion

Fit this if your application genuinely needs location while it is in the background and you are willing to pay for it at release time, because the battery argument only pays off if you are sampling continuously rather than on a timer. The motion-detection approach is the substance: the SDK decides from the accelerometer, gyroscope and magnetometer whether the device is moving, and turns location services off when it is not, which is a different design from a periodic wake-up and a different battery profile. Four things to settle before you start. Whether you are on the current major version, because keys from the previous one do not carry over and the previous line lives on a branch rather than on a tag. Whether you need Expo support, which is a plugin in this repository compiled by the build script rather than a separate package. What your license buys, since the source is MIT and the key is required only for release builds, which means development costs nothing and shipping costs something. And whether the motion states match your use, because a delivery job that visits five addresses a day and a commute tracker are very different workloads for the same heuristic.

Frequently asked questions

Does react-native-background-geolocation need a licence key?

A licence is required for release builds on both iOS and Android, while debug builds are fully functional with no licence at all. Keys issued for the previous major version do not work with the current one and have to be generated from the customer dashboard, and a free thirty day trial licence is available for testing a release build.

How does react-native-background-geolocation conserve battery?

It uses motion-detection APIs, naming the accelerometer, gyroscope and magnetometer, to decide whether the device is moving or stationary. When moving, recording starts automatically at the configured distanceFilter in metres; when stationary, location services turn off automatically to conserve battery.

Does react-native-background-geolocation support Expo?

Yes, and this repository serves both React Native and Expo. The Expo support lives in a plugin directory compiled by the package's build script, with a plugin entry point at the root of the repository, so no separate Expo package is needed.

What is the difference between v4 and v5 of react-native-background-geolocation?

The current line is the fifth major version, and the previous one is kept on a branch named for its own last release rather than on a tag. Licence keys issued for the previous version do not work with the current one and must be regenerated from the customer dashboard, and a migration guide versioned for the 5.0.0 release lives under the help directory.

What does building react-native-background-geolocation actually build?

Only the Expo plugin: the build script removes that plugin's build directory and compiles it, and the step before publishing runs the same script. The manifest's main field points into the source directory, so the JavaScript library ships as source rather than compiled, with the native code shipped alongside it.

How are the tests run for react-native-background-geolocation?

One command runs a JavaScript test runner and then type-checks a separate types test project with the compiler in no-emit mode. The repository also carries two test directories, a mocks directory and a test runner configuration file at the top level.

Official sources

  1. Issues
  2. License: MIT
  3. Project website
  4. README
  5. transistorsoft/react-native-background-geolocation on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/transistorsoft-react-native-background-geolocation.svg)](https://hysenlabs.com/projects/transistorsoft-react-native-background-geolocation)