Skip to content

[Bug]: Android: UserLocation never updates again after the Activity is destroyed while the process lives (onHostDestroy sets LocationManager nStarts = -1000) #4406

Closed

Description

@juiceboxweb

Mapbox Implementation

Mapbox

Mapbox Version

default

React Native Version

0.85.3 (New Architecture, bridgeless)

Platform

Android

@rnmapbox/maps version

10.3.1 (same code on main / v10.3.11)

Standalone component to reproduce

import React from 'react';
import Mapbox from '@rnmapbox/maps';

export default function App() {
  return (
    <Mapbox.MapView style={{ flex: 1 }}>
      <Mapbox.Camera followUserLocation followZoomLevel={16} />
      <Mapbox.UserLocation
        visible={false}
        onUpdate={loc => console.log('onUpdate', loc.coords.latitude, loc.coords.longitude)}
      />
    </Mapbox.MapView>
  );
}

Observed behavior and steps to reproduce

  1. Run an app with the component above. onUpdate fires as expected.
  2. Have something keep the app process alive without the Activity, e.g. a running foreground service.
  3. Leave the app in a way that destroys the Activity while the service keeps the process alive.
  4. Reopen the app. A new Activity is created in the same process.

Seen on a Samsung Galaxy S23+ running Android 16.
5. onUpdate never fires again, and the map never locates. No location request reaches the OS: adb shell dumpsys location shows no registration from the map. This holds until the process is killed.

In our logs, ReactHost.onHostDestroy fires in the same pid that later remounts the map.

This looks like the same symptom as #3965 ("UserLocation stops updating after restarting app with background foregroundService on Android"), which was closed as not planned without a root cause. Here is one.

Expected behavior

Location updates resume when the new Activity resumes, as they do after a plain pause/resume.

Notes / preliminary analysis

Two problems in android/.../modules/RNMBXLocationModule.kt and location/LocationManager.kt:

  1. onHostDestroy permanently disables the process-wide LocationManager. onHostDestroy calls locationManager?.destroy(), which disposes the engine and sets nStarts = -1000. LocationManager is a singleton that outlives the Activity, and startCounted() only enables the engine when nStarts == 1. From then on no start() can re-enable it for the life of the process. onHostDestroy fires on every Activity destroy, not only on React instance teardown, so a surviving process (foreground service, "Don't keep activities", system reclaiming a background Activity) ends up with a dead location feed. The location puck shares the same counter (LocationComponentManager), so it is affected too.

  2. start() counts twice. start() calls locationManager?.startCounted() and then startLocationManager(), which calls startCounted() again. stop() → stopLocationManager() calls stopCounted() once. The count can therefore never return to 0, so stop() never disposes the engine.

We're applying the patch below with patch-package. It compiles; in our app the screen that hit this now uses a different location source, so we haven't exercised the patched path on a device yet.

         override fun onHostDestroy() {
-            locationManager?.destroy()
+            // The Activity can be destroyed while the process (and this module) lives on.
+            // Pause instead; the next Activity's onHostResume re-enables. Teardown is in invalidate().
+            locationManager?.pause()
         }
 ...
+    override fun invalidate() {
+        reactApplicationContext.removeLifecycleEventListener(lifecycleEventListener)
+        stopLocationManager()
+        super.invalidate()
+    }
+
     @ReactMethod
     override fun start(minDisplacement: Double) {
-        isEnabled = true
         mMinDisplacement = minDisplacement.toFloat()
-        locationManager?.startCounted()
+        // One count per enabled module, matching the single stopCounted() in stop().
+        if (isEnabled) return
+        isEnabled = true
         startLocationManager()
     }

Additional links and references

Activity

  1. added a commit that references this issue on Nov 9, 2026
    51dee02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions