Required Reading
Plugin Version
5.1.1
Mobile operating-system(s)
Device Manufacturer(s) and Model(s)
Motorola Edge 50 Fusion
Device operating-systems(s)
Android 16
React Native / Expo version
No response
What happened?
On Android, background location tracking stops delivering onLocation events when desiredAccuracy is set to MEDIUM and the tracking screen loses focus. Switching to HIGH accuracy restores correct behaviour immediately. The foreground service notification stays visible, giving a false impression that tracking is active.
Expected Behaviour
MEDIUM accuracy should continue delivering location updates on Android when the screen that started tracking loses focus, consistent with HIGH accuracy behaviour.
Actual Behaviour
onLocation events stop firing entirely when desiredAccuracy is MEDIUM and the Android Activity's screen is no longer focused. The foreground service notification remains visible, giving a false impression of active tracking. No error or warning is emitted.
Additional Notes
- iOS is unaffected — both
MEDIUM and HIGH behave correctly on iOS.
- The Android Fused Location Provider (FLP) appears to deprioritise
MEDIUM accuracy requests when the requesting Activity loses focus. HIGH forces the GPS hardware directly and is not subject to this deprioritisation.
- Workaround: Use
HIGH accuracy. This increases battery consumption (~8× vs MEDIUM) which is undesirable for long-duration ride tracking.
- Setting
fastestLocationUpdateInterval to a lower value (e.g. 500ms) does not resolve the issue with MEDIUM.
Plugin Code and/or Config
# `app/_layout.tsx`
import { Stack } from "expo-router";
import { useEffect, useRef } from "react";
import BackgroundGeolocation, {
Subscription,
} from "react-native-background-geolocation";
import { TrackingProvider, useTracking } from "../contexts/tracking";
function BackgroundGeolocationSetup() {
const { setIsTracking } = useTracking();
const subscriptions = useRef<Subscription[]>([]);
useEffect(() => {
const subs = subscriptions.current;
subs.push(
BackgroundGeolocation.onLocation((location) => {
console.log("[onLocation]", location);
}),
);
subs.push(
BackgroundGeolocation.onEnabledChange((enabled) => {
setIsTracking(enabled);
}),
);
// ⚠️ Bug: change MEDIUM → HIGH to observe the difference
BackgroundGeolocation.ready({
geolocation: {
desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.Medium, // ❌ breaks background updates
distanceFilter: 1,
},
android: {
locationUpdateInterval: 1000,
fastestLocationUpdateInterval: 2000,
},
app: {
heartbeatInterval: 60,
stopOnTerminate: false,
startOnBoot: true,
},
logger: {
debug: true,
logLevel: BackgroundGeolocation.LogLevel.Verbose,
},
}).then((state) => {
setIsTracking(state.enabled);
});
return () => subs.forEach((s) => s.remove());
}, [setIsTracking]);
return null;
}
export default function RootLayout() {
return (
<TrackingProvider>
<BackgroundGeolocationSetup />
<Stack>
<Stack.Screen name="index" options={{ title: "Home" }} />
<Stack.Screen name="settings" options={{ title: "Settings" }} />
</Stack>
</TrackingProvider>
);
}
### `app/index.tsx`
import { router } from "expo-router";
import { Pressable, StyleSheet, Text, View } from "react-native";
import BackgroundGeolocation from "react-native-background-geolocation";
import { useTracking } from "../contexts/tracking";
export default function IndexScreen() {
const { isTracking } = useTracking();
const onToggleTracking = async () => {
const state = await BackgroundGeolocation.getState();
if (state.enabled) {
await BackgroundGeolocation.stop();
} else {
await BackgroundGeolocation.start();
}
};
return (
<View style={styles.container}>
<Text style={styles.status}>
{isTracking ? "✅ Tracking active" : "❌ Tracking inactive"}
</Text>
{/* Navigate away to trigger the bug — onLocation stops firing */}
<Pressable style={styles.button} onPress={() => router.push("/settings")}>
<Text style={styles.buttonText}>Go to Settings (triggers bug)</Text>
</Pressable>
<Pressable style={styles.button} onPress={onToggleTracking}>
<Text style={styles.buttonText}>
{isTracking ? "Stop Tracking" : "Start Tracking"}
</Text>
</Pressable>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, alignItems: "center", justifyContent: "center", gap: 16 },
status: { fontSize: 16, fontWeight: "600" },
button: {
backgroundColor: "#007AFF",
paddingVertical: 14,
paddingHorizontal: 24,
borderRadius: 8,
minWidth: 220,
alignItems: "center",
},
buttonText: { color: "#fff", fontSize: 15, fontWeight: "600" },
});
---
## Config Comparison
### ❌ Broken — `MEDIUM` accuracy
BackgroundGeolocation.ready({
geolocation: {
desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.Medium,
distanceFilter: 1,
},
android: {
locationUpdateInterval: 1000,
fastestLocationUpdateInterval: 2000,
},
});
`onLocation` fires normally while the screen is focused. As soon as the user navigates to another screen, events stop completely. No error is thrown.
### ✅ Works — `HIGH` accuracy
BackgroundGeolocation.ready({
geolocation: {
desiredAccuracy: BackgroundGeolocation.DesiredAccuracy.High, // only change
distanceFilter: 1,
},
android: {
locationUpdateInterval: 1000,
fastestLocationUpdateInterval: 2000,
},
});
Relevant log output
Required Reading
Plugin Version
5.1.1
Mobile operating-system(s)
Device Manufacturer(s) and Model(s)
Motorola Edge 50 Fusion
Device operating-systems(s)
Android 16
React Native / Expo version
No response
What happened?
On Android, background location tracking stops delivering
onLocationevents whendesiredAccuracyis set toMEDIUMand the tracking screen loses focus. Switching toHIGHaccuracy restores correct behaviour immediately. The foreground service notification stays visible, giving a false impression that tracking is active.Expected Behaviour
MEDIUMaccuracy should continue delivering location updates on Android when the screen that started tracking loses focus, consistent withHIGHaccuracy behaviour.Actual Behaviour
onLocationevents stop firing entirely whendesiredAccuracyisMEDIUMand the Android Activity's screen is no longer focused. The foreground service notification remains visible, giving a false impression of active tracking. No error or warning is emitted.Additional Notes
MEDIUMandHIGHbehave correctly on iOS.MEDIUMaccuracy requests when the requesting Activity loses focus.HIGHforces the GPS hardware directly and is not subject to this deprioritisation.HIGHaccuracy. This increases battery consumption (~8× vsMEDIUM) which is undesirable for long-duration ride tracking.fastestLocationUpdateIntervalto a lower value (e.g.500ms) does not resolve the issue withMEDIUM.Plugin Code and/or Config
Relevant log output