CORE JSC

International Technology Partnership

Mobile Development

Fixing React Native Background Location Updates That Stop After a Few Minutes on Android (Doze Mode)

A location-tracking feature works perfectly while the app is open, and even for a while after it's backgrounded — then updates simply stop arriving, with no error and no crash, usually somewhere between a few minutes and half an hour later. It isn't the location API failing; it's Android itself deciding the app no longer deserves to keep running.

Core JSC Team·October 18, 2026
React NativeAndroidMobile DevelopmentBackground LocationBattery Optimization

The Problem

A feature that needs the device's location in the background — delivery tracking, a fitness app logging a route, a geofencing alert — works flawlessly while the app is in the foreground, and often continues working for some time after the user switches to another app or locks the screen. Then, without any error being thrown and without the app crashing, location updates simply stop arriving. The exact delay before this happens varies between devices and even between runs on the same device, which makes it feel intermittent rather than a reliable, reproducible bug.

Why It Happens

Android's Doze mode suspends background work, including location updates, after a period of device inactivity

Starting with Android 6.0, the operating system enters "Doze" mode when the device has been stationary and the screen off for a while, specifically to reduce background battery drain across all installed apps. Doze restricts network access, defers background jobs, and — critically for this bug — suppresses regular location updates for apps that aren't explicitly exempted, batching or withholding them until Doze lets up, which from the app's perspective looks exactly like updates silently stopping.

A plain foreground-looking location subscription doesn't survive the transition to a true background state

Many React Native location libraries default to a straightforward subscription model that works great while the app's JavaScript context is still alive and running. Once Android fully backgrounds the app — rather than just putting it in a brief inactive state — that JavaScript context can itself be suspended or killed by the OS, independent of Doze, unless the app has specifically set up a foreground service or an equivalent mechanism that tells Android this work needs to keep running.

Manufacturer-specific battery optimization layers add a second, independent restriction on top of stock Android's

Several Android device manufacturers ship their own, more aggressive battery management on top of what stock Android already does, with app-specific "battery optimization" or "sleeping apps" lists that can kill background processes even for apps correctly using a foreground service and properly requesting Doze exemptions through the standard Android APIs. This means a fix that's complete and correct on a stock Android device or emulator can still fail on a specific popular phone brand, for reasons entirely outside the app's own code.

The Fix

1. Run background location tracking through a proper foreground service, not a bare subscription

// Using a library that exposes explicit foreground-service background tracking,
// rather than a plain watchPosition-style subscription:
import BackgroundGeolocation from "react-native-background-geolocation";

BackgroundGeolocation.ready({
  foregroundService: true, // keeps a persistent notification and tells Android this must keep running
  locationUpdateInterval: 10000,
  stopOnTerminate: false,
  startOnBoot: true,
});

A foreground service requires showing a persistent, visible notification — which is the trade-off Android makes for letting the work bypass the restrictions that would otherwise apply to ordinary background processes — and it's specifically the mechanism libraries like this use to actually survive Doze and app-backgrounding rather than being silently suspended.

2. Explicitly request exemption from battery optimization for this app, through the standard Android API

// Native Android side (or via a library wrapper that exposes this):
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);

This system dialog, which the user has to explicitly approve, is the standard-Android mechanism for telling the OS that a specific app's background work shouldn't be subject to the usual Doze restrictions — it won't address manufacturer-specific battery layers on its own, but it's the baseline requirement before investigating anything device-specific.

3. Test specifically on the manufacturer-heavy devices the app actually needs to support, not just a stock emulator

Check manufacturer-specific guidance sites (e.g. dontkillmyapp.com) for the exact
settings path on a given device brand, since each manufacturer's battery
management UI and terminology differs.

Because manufacturer battery layers vary so widely in both behavior and where their settings live, reproducing the issue on the actual hardware (or device-specific emulator images) the target users run is the only reliable way to confirm a fix actually survives that manufacturer's specific restrictions, rather than just stock Android's Doze mode.

4. Surface a clear in-app prompt asking the user to disable battery optimization for the app, rather than relying on them finding the setting unprompted

// Check whether the exemption is already granted, and if not, explain why before prompting:
const isIgnoringOptimizations = await checkBatteryOptimizationStatus();
if (!isIgnoringOptimizations) {
  showExplanationDialog(
    "For accurate background tracking, please allow this app to run without battery restrictions."
  );
}

Since the battery-optimization exemption is a setting the user has to grant explicitly and manufacturers often bury it several menus deep, a clear in-app explanation of why it's being requested — shown before the system prompt, not instead of it — meaningfully improves the odds a user actually grants it rather than dismissing an unexplained permission dialog.

Why This Works

Each fix addresses a different layer of the same underlying restriction. A foreground service is the mechanism Android itself provides for background work to be treated differently from an ordinary suspendable background process, which is the baseline requirement for surviving backgrounding at all. Requesting the standard battery-optimization exemption addresses stock Android's Doze restrictions specifically. Testing on manufacturer-heavy devices surfaces the additional, non-standard restrictions that stock-Android testing alone will never reveal. And a clear in-app explanation before the system prompt improves the real-world odds that users actually grant the exemption the feature depends on, rather than treating it as just another permission dialog.

Conclusion

Background location updates that quietly stop on Android are almost never a bug in the location API itself — they're Android's Doze mode, and often a manufacturer's own battery management layer on top of it, suspending background work that wasn't explicitly set up to be exempt from those restrictions. Run the tracking through a proper foreground service rather than a bare subscription, explicitly request the standard battery-optimization exemption, test on the specific manufacturer-heavy devices the app needs to support rather than a stock emulator alone, and give users a clear explanation before asking them to grant the exemption the feature actually needs.