Skip to content

[Bug]: Android: Blue point of LocationPuck not shown if GPS was enabled from app #4106

@nikita-filimonau

Description

@nikita-filimonau

Mapbox Implementation

Mapbox

Mapbox Version

11.15.2

React Native Version

0.81.5

React Native Architecture

New Architecture (Fabric/TurboModules)

Platform

Android

@rnmapbox/maps version

10.2.7

Standalone component to reproduce

We are experiencing an issue where the User Location Puck (the blue circle) does not render if the application is launched while the device's Location Services (GPS) are disabled, and then enabled while the app is running.

The puck only appears correctly if Location Services are enabled before the application starts.

We use next libraries and versions:

{
  "@rnmapbox/maps": "10.2.7",
  "expo": "54.0.25",
  "react": "19.1.0",
  "react-native": "0.81.5"
}

We use next libraries and versions:

import React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import { MapView, Camera, UserLocation, Logger } from '@rnmapbox/maps';

// Optional: Increase logging to see location updates in console
Logger.setLogCallback((log) => {
  const { message } = log;
  if (message.match('Requesting location results')) console.log(message);
});

const styles = StyleSheet.create({
  page: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  container: { height: '100%', width: '100%' },
  map: { flex: 1 },
});

class BugReportExample extends React.Component {
  render() {
    return (
      <View style={styles.page}>
        <View style={styles.container}>
          <MapView style={styles.map}>
            <Camera
              defaultSettings={{
                centerCoordinate: [-74.00597, 40.71427],
                zoomLevel: 14,
              }}
              followUserLocation={true}
              followUserMode={'normal'}
            />
            
            {/* The UserLocation component handles the "blue puck".
              It should automatically listen to location updates.
            */}
            <UserLocation
              visible={true}
              showsUserHeadingIndicator={true}
              androidRenderMode={'gps'} // Explicitly trying GPS mode
              onUpdate={(location) => {
                console.log('Location updated:', location);
              }}
            />
          </MapView>
        </View>
      </View>
    );
  }
}

export default BugReportExample;

Observed behavior and steps to reproduce

Steps to Reproduce:

  1. Disable Location Services (GPS) on the device (Android).
  2. Launch the application with the reproduction component.
  3. Observe that the map loads (UserLocation is expected to be missing or waiting).
  4. Enable Location Services (GPS) via the device System Settings / Control Center.
  5. Return to the application.
  6. Observe that the UserLocation puck (blue circle) does not appear, even though permissions are granted and the service is now active.

Expected behavior

The UserLocation puck should appear automatically (or after a re-render) once Location Services become available and the app receives the location update.

Notes / preliminary analysis

We have created a patch that fixes this issue. It has been tested and works as expected. We believe it would be a valuable addition to the library. Please find the proposed fix below

diff --git a/android/src/main/java/com/rnmapbox/rnmbx/components/location/LocationComponentManager.kt b/android/src/main/java/com/rnmapbox/rnmbx/components/location/LocationComponentManager.kt
index c429ffcaddd84e41c78c6461e18d96092c05623f..ae7685ec56cb5d6de1dfb65104e8c2c2cbbed3ea 100644
--- a/android/src/main/java/com/rnmapbox/rnmbx/components/location/LocationComponentManager.kt
+++ b/android/src/main/java/com/rnmapbox/rnmbx/components/location/LocationComponentManager.kt
@@ -174,10 +174,7 @@ class LocationComponentManager(mapView: RNMBXMapView, context: Context) {
     }
 
     private fun useMapLocationProvider(mapView: RNMBXMapView) {
-        val provider = mapView.mapView.location.getLocationProvider()
-        if (provider != null) {
-            mLocationManager.provider = provider
-        }
+        mapView.mapView.location.setLocationProvider(mLocationManager.provider)
     }
 
 
diff --git a/android/src/main/java/com/rnmapbox/rnmbx/location/LocationManager.kt b/android/src/main/java/com/rnmapbox/rnmbx/location/LocationManager.kt
index daa77e534eb3787778010e98a71621822f616dca..220e3918ed1b5c8016bd55511a2c4c2224fd85cd 100644
--- a/android/src/main/java/com/rnmapbox/rnmbx/location/LocationManager.kt
+++ b/android/src/main/java/com/rnmapbox/rnmbx/location/LocationManager.kt
@@ -185,8 +185,17 @@ class LocationManager private constructor(private val context: Context) : Locati
             return
         }
 
-        // remove existing listeners
-        engine?.removeLocationUpdates(this)
+        try {
+            engine?.removeLocationUpdates(this)
+        } catch (e: Exception) {
+            // ignore
+        }
+
+        buildEngineRequest()
+
+        if (locationProvider is LocationProviderForEngine) {
+            (locationProvider as LocationProviderForEngine).mEngine = engine
+        }
 
         // refresh location engine request with new values
 

Additional links and references

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🪲Something isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions