@maplibre/maplibre-react-native 11.0.0-alpha.12 → 11.0.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/android/src/main/java/org/maplibre/reactnative/MLRNPackage.kt +5 -5
  2. package/android/src/main/java/org/maplibre/reactnative/components/camera/MLRNCamera.kt +27 -39
  3. package/android/src/main/java/org/maplibre/reactnative/events/constants/EventKeys.java +0 -4
  4. package/android/src/main/java/org/maplibre/reactnative/events/constants/EventTypes.java +0 -1
  5. package/android/src/main/java/org/maplibre/reactnative/location/LocationManager.kt +165 -0
  6. package/android/src/main/java/org/maplibre/reactnative/location/TrackUserLocationMode.kt +0 -1
  7. package/android/src/main/java/org/maplibre/reactnative/location/TrackUserLocationState.kt +15 -0
  8. package/android/src/main/java/org/maplibre/reactnative/location/UserLocation.kt +40 -0
  9. package/android/src/main/java/org/maplibre/reactnative/location/engine/DefaultLocationEngineProvider.kt +18 -0
  10. package/android/src/main/java/org/maplibre/reactnative/location/engine/LocationEngineProvidable.kt +8 -0
  11. package/android/src/main/java/org/maplibre/reactnative/modules/MLRNLocationModule.kt +153 -0
  12. package/android/src/main/java/org/maplibre/reactnative/modules/MLRNModule.java +0 -5
  13. package/android/src/main/location-engine-default/org/maplibre/reactnative/location/engine/LocationEngineProvider.kt +10 -0
  14. package/android/src/main/location-engine-google/org/maplibre/reactnative/location/engine/GoogleLocationEngineImpl.kt +131 -0
  15. package/android/src/main/location-engine-google/org/maplibre/reactnative/location/engine/GoogleLocationEngineProvider.kt +28 -0
  16. package/android/src/main/location-engine-google/org/maplibre/reactnative/location/engine/LocationEngineProvider.kt +10 -0
  17. package/ios/components/camera/MLRNCameraComponentView.mm +5 -1
  18. package/ios/modules/location/MLRNLocation.h +0 -1
  19. package/ios/modules/location/MLRNLocation.m +3 -3
  20. package/ios/modules/location/MLRNLocationManager.h +1 -3
  21. package/ios/modules/location/MLRNLocationManager.m +1 -4
  22. package/ios/modules/location/MLRNLocationManagerDelegate.h +0 -2
  23. package/ios/modules/location/MLRNLocationModule.h +4 -4
  24. package/ios/modules/location/MLRNLocationModule.mm +56 -0
  25. package/ios/modules/mlrn/MLRNModule.m +0 -5
  26. package/ios/utils/MLRNEventTypes.h +0 -2
  27. package/ios/utils/MLRNEventTypes.m +0 -2
  28. package/lib/commonjs/components/camera/Camera.js.map +1 -1
  29. package/lib/commonjs/components/camera/CameraNativeComponent.ts +6 -1
  30. package/lib/commonjs/components/user-location/UserLocation.js +3 -3
  31. package/lib/commonjs/components/user-location/UserLocation.js.map +1 -1
  32. package/lib/commonjs/index.js +2 -2
  33. package/lib/commonjs/index.js.map +1 -1
  34. package/lib/commonjs/modules/location/LocationManager.js +46 -57
  35. package/lib/commonjs/modules/location/LocationManager.js.map +1 -1
  36. package/lib/commonjs/modules/location/NativeLocationModule.js +9 -0
  37. package/lib/commonjs/modules/location/NativeLocationModule.js.map +1 -0
  38. package/lib/commonjs/modules/location/requestAndroidLocationPermissions.js +14 -0
  39. package/lib/commonjs/modules/location/requestAndroidLocationPermissions.js.map +1 -0
  40. package/lib/module/components/camera/Camera.js.map +1 -1
  41. package/lib/module/components/camera/CameraNativeComponent.ts +6 -1
  42. package/lib/module/components/user-location/UserLocation.js +3 -3
  43. package/lib/module/components/user-location/UserLocation.js.map +1 -1
  44. package/lib/module/index.js +1 -1
  45. package/lib/module/index.js.map +1 -1
  46. package/lib/module/modules/location/LocationManager.js +45 -57
  47. package/lib/module/modules/location/LocationManager.js.map +1 -1
  48. package/lib/module/modules/location/NativeLocationModule.js +5 -0
  49. package/lib/module/modules/location/NativeLocationModule.js.map +1 -0
  50. package/lib/module/modules/location/requestAndroidLocationPermissions.js +11 -0
  51. package/lib/module/modules/location/requestAndroidLocationPermissions.js.map +1 -0
  52. package/lib/typescript/commonjs/src/components/camera/Camera.d.ts +1 -1
  53. package/lib/typescript/commonjs/src/components/camera/Camera.d.ts.map +1 -1
  54. package/lib/typescript/commonjs/src/components/camera/CameraNativeComponent.d.ts +2 -1
  55. package/lib/typescript/commonjs/src/components/camera/CameraNativeComponent.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/src/components/user-location/UserLocation.d.ts +3 -3
  57. package/lib/typescript/commonjs/src/components/user-location/UserLocation.d.ts.map +1 -1
  58. package/lib/typescript/commonjs/src/index.d.ts +2 -2
  59. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  60. package/lib/typescript/commonjs/src/modules/location/LocationManager.d.ts +42 -22
  61. package/lib/typescript/commonjs/src/modules/location/LocationManager.d.ts.map +1 -1
  62. package/lib/typescript/commonjs/src/modules/location/NativeLocationModule.d.ts +24 -0
  63. package/lib/typescript/commonjs/src/modules/location/NativeLocationModule.d.ts.map +1 -0
  64. package/lib/typescript/commonjs/src/modules/location/requestAndroidLocationPermissions.d.ts +5 -0
  65. package/lib/typescript/commonjs/src/modules/location/requestAndroidLocationPermissions.d.ts.map +1 -0
  66. package/lib/typescript/module/src/components/camera/Camera.d.ts +1 -1
  67. package/lib/typescript/module/src/components/camera/Camera.d.ts.map +1 -1
  68. package/lib/typescript/module/src/components/camera/CameraNativeComponent.d.ts +2 -1
  69. package/lib/typescript/module/src/components/camera/CameraNativeComponent.d.ts.map +1 -1
  70. package/lib/typescript/module/src/components/user-location/UserLocation.d.ts +3 -3
  71. package/lib/typescript/module/src/components/user-location/UserLocation.d.ts.map +1 -1
  72. package/lib/typescript/module/src/index.d.ts +2 -2
  73. package/lib/typescript/module/src/index.d.ts.map +1 -1
  74. package/lib/typescript/module/src/modules/location/LocationManager.d.ts +42 -22
  75. package/lib/typescript/module/src/modules/location/LocationManager.d.ts.map +1 -1
  76. package/lib/typescript/module/src/modules/location/NativeLocationModule.d.ts +24 -0
  77. package/lib/typescript/module/src/modules/location/NativeLocationModule.d.ts.map +1 -0
  78. package/lib/typescript/module/src/modules/location/requestAndroidLocationPermissions.d.ts +5 -0
  79. package/lib/typescript/module/src/modules/location/requestAndroidLocationPermissions.d.ts.map +1 -0
  80. package/package.json +5 -3
  81. package/src/components/camera/Camera.tsx +2 -6
  82. package/src/components/camera/CameraNativeComponent.ts +6 -1
  83. package/src/components/user-location/UserLocation.tsx +9 -7
  84. package/src/index.ts +3 -2
  85. package/src/modules/location/LocationManager.ts +90 -97
  86. package/src/modules/location/NativeLocationModule.ts +31 -0
  87. package/src/modules/location/requestAndroidLocationPermissions.ts +8 -0
  88. package/android/src/main/java/org/maplibre/reactnative/events/LocationEvent.java +0 -100
  89. package/android/src/main/java/org/maplibre/reactnative/events/TrackUserLocationChangeEvent.kt +0 -24
  90. package/android/src/main/java/org/maplibre/reactnative/location/LocationManager.java +0 -160
  91. package/android/src/main/java/org/maplibre/reactnative/location/TrackUserLocationState.java +0 -15
  92. package/android/src/main/java/org/maplibre/reactnative/location/UserLocation.java +0 -59
  93. package/android/src/main/java/org/maplibre/reactnative/location/engine/DefaultLocationEngineProvider.java +0 -18
  94. package/android/src/main/java/org/maplibre/reactnative/location/engine/LocationEngineProvidable.java +0 -9
  95. package/android/src/main/java/org/maplibre/reactnative/modules/MLRNLocationModule.java +0 -158
  96. package/android/src/main/location-engine-default/org/maplibre/reactnative/location/engine/LocationEngineProvider.java +0 -12
  97. package/android/src/main/location-engine-google/org/maplibre/reactnative/location/engine/GoogleLocationEngineImpl.java +0 -151
  98. package/android/src/main/location-engine-google/org/maplibre/reactnative/location/engine/GoogleLocationEngineProvider.java +0 -24
  99. package/android/src/main/location-engine-google/org/maplibre/reactnative/location/engine/LocationEngineProvider.java +0 -12
  100. package/ios/modules/location/MLRNLocationModule.m +0 -76
  101. package/lib/commonjs/requestAndroidLocationPermissions.js +0 -25
  102. package/lib/commonjs/requestAndroidLocationPermissions.js.map +0 -1
  103. package/lib/module/requestAndroidLocationPermissions.js +0 -21
  104. package/lib/module/requestAndroidLocationPermissions.js.map +0 -1
  105. package/lib/typescript/commonjs/src/requestAndroidLocationPermissions.d.ts +0 -2
  106. package/lib/typescript/commonjs/src/requestAndroidLocationPermissions.d.ts.map +0 -1
  107. package/lib/typescript/module/src/requestAndroidLocationPermissions.d.ts +0 -2
  108. package/lib/typescript/module/src/requestAndroidLocationPermissions.d.ts.map +0 -1
  109. package/src/requestAndroidLocationPermissions.ts +0 -29
@@ -55,7 +55,7 @@ class MLRNPackage : BaseReactPackage() {
55
55
 
56
56
  MLRNOfflineModule.REACT_CLASS -> return MLRNOfflineModule(reactContext)
57
57
  MLRNSnapshotModule.NAME -> return MLRNSnapshotModule(reactContext)
58
- MLRNLocationModule.REACT_CLASS -> return MLRNLocationModule(reactContext)
58
+ MLRNLocationModule.NAME -> return MLRNLocationModule(reactContext)
59
59
  MLRNLogging.REACT_CLASS -> return MLRNLogging(reactContext)
60
60
  }
61
61
 
@@ -111,13 +111,13 @@ class MLRNPackage : BaseReactPackage() {
111
111
  isTurboModule = true
112
112
  )
113
113
 
114
- moduleInfos[MLRNLocationModule.REACT_CLASS] = ReactModuleInfo(
115
- MLRNLocationModule.REACT_CLASS,
116
- MLRNLocationModule.REACT_CLASS,
114
+ moduleInfos[MLRNLocationModule.NAME] = ReactModuleInfo(
115
+ MLRNLocationModule.NAME,
116
+ MLRNLocationModule.NAME,
117
117
  canOverrideExistingModule = false,
118
118
  needsEagerInit = false,
119
119
  isCxxModule = false,
120
- isTurboModule = false
120
+ isTurboModule = true
121
121
  )
122
122
 
123
123
  moduleInfos[MLRNLogging.REACT_CLASS] = ReactModuleInfo(
@@ -1,14 +1,16 @@
1
1
  package org.maplibre.reactnative.components.camera
2
2
 
3
+ import android.Manifest
3
4
  import android.content.Context
4
5
  import android.location.Location
5
6
  import android.util.AttributeSet
7
+ import androidx.annotation.RequiresPermission
6
8
  import com.facebook.react.bridge.Arguments
7
9
  import com.facebook.react.bridge.ReactContext
8
10
  import com.facebook.react.bridge.ReadableMap
9
11
  import com.facebook.react.bridge.WritableMap
10
- import com.facebook.react.bridge.WritableNativeMap
11
12
  import com.facebook.react.uimanager.UIManagerHelper
13
+ import com.facebook.react.uimanager.events.Event
12
14
  import com.facebook.react.uimanager.events.EventDispatcher
13
15
  import org.maplibre.android.camera.CameraPosition
14
16
  import org.maplibre.android.camera.CameraUpdateFactory.newCameraPosition
@@ -22,8 +24,6 @@ import org.maplibre.reactnative.components.AbstractMapFeature
22
24
  import org.maplibre.reactnative.components.camera.constants.CameraEasing
23
25
  import org.maplibre.reactnative.components.location.LocationComponentManager
24
26
  import org.maplibre.reactnative.components.mapview.MLRNMapView
25
- import org.maplibre.reactnative.events.MapChangeEvent
26
- import org.maplibre.reactnative.events.TrackUserLocationChangeEvent
27
27
  import org.maplibre.reactnative.location.LocationManager
28
28
  import org.maplibre.reactnative.location.LocationManager.OnUserLocationChange
29
29
  import org.maplibre.reactnative.location.TrackUserLocationMode
@@ -63,13 +63,12 @@ class MLRNCamera(context: Context) : AbstractMapFeature(
63
63
 
64
64
 
65
65
  private val locationChangeListener: OnUserLocationChange = object : OnUserLocationChange {
66
- override fun onLocationChange(nextLocation: Location) {
66
+ override fun onLocationChange(location: Location) {
67
67
  if (mapView!!.mapLibreMap == null || locationComponentManager == null || !locationComponentManager!!.hasLocationComponent() || trackUserLocation == TrackUserLocationMode.NONE) {
68
68
  return
69
69
  }
70
70
 
71
- userLocation.currentLocation = nextLocation
72
- sendUserLocationUpdateEvent(nextLocation)
71
+ userLocation.setCurrentLocation(location);
73
72
  }
74
73
  }
75
74
 
@@ -103,6 +102,7 @@ class MLRNCamera(context: Context) : AbstractMapFeature(
103
102
  }
104
103
  }
105
104
 
105
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
106
106
  override fun addToMap(mapView: MLRNMapView) {
107
107
  this@MLRNCamera.mapView = mapView
108
108
 
@@ -192,7 +192,7 @@ class MLRNCamera(context: Context) : AbstractMapFeature(
192
192
  private fun updateUserTrackingMode(trackUserLocationMode: Int) {
193
193
  userLocation.trackingMode = trackUserLocationMode
194
194
 
195
- val event = TrackUserLocationChangeEvent(surfaceId, id, trackUserLocationMode)
195
+ val event = OnTrackUserLocationChangeEvent(surfaceId, id, trackUserLocationMode)
196
196
  eventDispatcher?.dispatchEvent(event)
197
197
  }
198
198
 
@@ -232,17 +232,6 @@ class MLRNCamera(context: Context) : AbstractMapFeature(
232
232
  return direction
233
233
  }
234
234
 
235
- private fun sendUserLocationUpdateEvent(location: Location?) {
236
- if (location == null) {
237
- return
238
- }
239
- // TODO: This has to be emitted from the proper Component
240
- val event = MapChangeEvent(
241
- surfaceId, id, "onUpdate", makeLocationChangePayload(location)
242
- )
243
- eventDispatcher?.dispatchEvent(event)
244
- }
245
-
246
235
  private fun updateUserLocationSignificantly() {
247
236
  userTrackingState = TrackUserLocationState.BEGAN
248
237
 
@@ -282,12 +271,13 @@ class MLRNCamera(context: Context) : AbstractMapFeature(
282
271
  mapView!!.moveCamera(cameraUpdate, callback)
283
272
  }
284
273
 
274
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
285
275
  private fun enableLocation() {
286
276
  if (!PermissionsManager.areLocationPermissionsGranted(context)) {
287
277
  return
288
278
  }
289
279
 
290
- if (!locationManager.isActive) {
280
+ if (!locationManager.isActive()) {
291
281
  locationManager.enable()
292
282
  }
293
283
 
@@ -385,25 +375,23 @@ class MLRNCamera(context: Context) : AbstractMapFeature(
385
375
  return mapView!!.mapLibreMap
386
376
  }
387
377
 
388
- // TODO: Update structure
389
- private fun makeLocationChangePayload(location: Location): WritableMap {
390
- val positionProperties: WritableMap = WritableNativeMap()
391
- val coordinates: WritableMap = WritableNativeMap()
392
-
393
- coordinates.putDouble("longitude", location.longitude)
394
- coordinates.putDouble("latitude", location.latitude)
395
- coordinates.putDouble("altitude", location.altitude)
396
- coordinates.putDouble("accuracy", location.accuracy.toDouble())
397
- // TODO
398
- // A better solution will be to pull the heading from the compass engine,
399
- // unfortunately the api is not public
400
- coordinates.putDouble("heading", location.bearing.toDouble())
401
- coordinates.putDouble("course", location.bearing.toDouble())
402
- coordinates.putDouble("speed", location.speed.toDouble())
403
-
404
- positionProperties.putMap("coords", coordinates)
405
- positionProperties.putDouble("timestamp", location.time.toDouble())
406
-
407
- return positionProperties
378
+
379
+ inner class OnTrackUserLocationChangeEvent(
380
+ surfaceId: Int,
381
+ viewId: Int,
382
+ private val trackUserLocationMode: Int
383
+ ) :
384
+ Event<OnTrackUserLocationChangeEvent>(surfaceId, viewId) {
385
+ override fun getEventName() = "onTrackUserLocationChange"
386
+
387
+ override fun getEventData(): WritableMap {
388
+ return Arguments.createMap().apply {
389
+ putString(
390
+ "trackUserLocation",
391
+ TrackUserLocationMode.toString(trackUserLocationMode)
392
+ )
393
+ }
394
+ }
408
395
  }
396
+
409
397
  }
@@ -6,8 +6,6 @@ public class EventKeys {
6
6
  // map events
7
7
  public static final String MAP_CLICK = ns("map.press");
8
8
  public static final String MAP_LONG_CLICK = ns("map.longpress");
9
- public static final String MAP_ONCHANGE = ns("map.change");
10
- public static final String MAP_ON_LOCATION_CHANGE = ns("map.location.change");
11
9
  public static final String MAP_ANDROID_CALLBACK = ns("map.androidcallback");
12
10
 
13
11
  // point annotation events
@@ -25,8 +23,6 @@ public class EventKeys {
25
23
  // images event
26
24
  public static final String IMAGES_MISSING = ns("images.missing");
27
25
 
28
- // location events
29
- public static final String USER_LOCATION_UPDATE = ns("user.location.update");
30
26
 
31
27
  private static String ns(String name) {
32
28
  return String.format("%s.%s", NAMESPACE, name);
@@ -4,7 +4,6 @@ public class EventTypes {
4
4
  // map event types
5
5
  public static final String MAP_CLICK = "press";
6
6
  public static final String MAP_LONG_CLICK = "longpress";
7
- public static final String USER_LOCATION_UPDATED = "userlocationdupdated";
8
7
 
9
8
  // point annotation event types
10
9
  public static final String ANNOTATION_SELECTED = "annotationselected";
@@ -0,0 +1,165 @@
1
+ package org.maplibre.reactnative.location
2
+
3
+ import android.Manifest
4
+ import android.content.Context
5
+ import android.location.Location
6
+ import android.os.Looper
7
+ import android.util.Log
8
+ import androidx.annotation.RequiresPermission
9
+ import org.maplibre.android.location.engine.LocationEngine
10
+ import org.maplibre.android.location.engine.LocationEngineCallback
11
+ import org.maplibre.android.location.engine.LocationEngineRequest
12
+ import org.maplibre.android.location.engine.LocationEngineResult
13
+ import org.maplibre.android.location.permissions.PermissionsManager
14
+ import org.maplibre.reactnative.location.engine.LocationEngineProvider
15
+ import java.lang.ref.WeakReference
16
+
17
+ class LocationManager private constructor(private val context: Context) :
18
+ LocationEngineCallback<LocationEngineResult> {
19
+ var engine: LocationEngine? = null
20
+ private set
21
+ private val listeners: MutableList<OnUserLocationChange> = ArrayList<OnUserLocationChange>()
22
+
23
+ private var mMinDisplacement = 0f
24
+ private var isActive = false
25
+ private var lastLocation: Location? = null
26
+
27
+ private var locationEngineRequest: LocationEngineRequest? = null
28
+
29
+ interface OnUserLocationChange {
30
+ fun onLocationChange(location: Location)
31
+ }
32
+
33
+ init {
34
+ this.buildEngineRequest()
35
+ }
36
+
37
+ private fun buildEngineRequest() {
38
+ this.engine = LocationEngineProvider().getLocationEngine(context)
39
+
40
+ locationEngineRequest = LocationEngineRequest.Builder(DEFAULT_INTERVAL_MILLIS)
41
+ .setFastestInterval(DEFAULT_FASTEST_INTERVAL_MILLIS)
42
+ .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
43
+ .setDisplacement(mMinDisplacement).build()
44
+ }
45
+
46
+ fun addLocationListener(listener: OnUserLocationChange?) {
47
+ if (!listeners.contains(listener)) {
48
+ listeners.add(listener!!)
49
+ }
50
+ }
51
+
52
+ fun removeLocationListener(listener: OnUserLocationChange?) {
53
+ if (listeners.contains(listener)) {
54
+ listeners.remove(listener)
55
+ }
56
+ }
57
+
58
+ fun setMinDisplacement(minDisplacement: Float) {
59
+ mMinDisplacement = minDisplacement
60
+ }
61
+
62
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
63
+ fun enable() {
64
+ if (!PermissionsManager.areLocationPermissionsGranted(context)) {
65
+ return
66
+ }
67
+
68
+ // Remove existing listeners
69
+ engine!!.removeLocationUpdates(this)
70
+
71
+ // Refresh location engine request with new values
72
+ this.buildEngineRequest()
73
+
74
+ // Add new listeners
75
+ engine!!.requestLocationUpdates(
76
+ locationEngineRequest!!, this, Looper.getMainLooper()
77
+ )
78
+
79
+ isActive = true
80
+ }
81
+
82
+
83
+ fun disable() {
84
+ engine!!.removeLocationUpdates(this)
85
+ isActive = false
86
+ }
87
+
88
+ fun dispose() {
89
+ if (this.engine == null) {
90
+ return
91
+ }
92
+
93
+ disable()
94
+ engine!!.removeLocationUpdates(this)
95
+ }
96
+
97
+ fun isActive(): Boolean {
98
+ return this.engine != null && this.isActive
99
+ }
100
+
101
+ val lastKnownLocation: Location?
102
+ get() {
103
+ if (this.engine == null) {
104
+ return null
105
+ }
106
+
107
+ return lastLocation
108
+ }
109
+
110
+
111
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
112
+ fun getLastKnownLocation(callback: LocationEngineCallback<LocationEngineResult?>) {
113
+ if (this.engine == null) {
114
+ callback.onFailure(Exception("LocationEngine not initialized"))
115
+ }
116
+
117
+ try {
118
+ engine!!.getLastLocation(callback)
119
+ } catch (exception: Exception) {
120
+ Log.w(LOG_TAG, exception)
121
+ callback.onFailure(exception)
122
+ }
123
+ }
124
+
125
+ fun onLocationChanged(location: Location) {
126
+ lastLocation = location
127
+ for (listener in listeners) {
128
+ listener.onLocationChange(location)
129
+ }
130
+ }
131
+
132
+ override fun onFailure(exception: Exception) {
133
+ // TODO handle this.
134
+ }
135
+
136
+ override fun onSuccess(result: LocationEngineResult?) {
137
+ val location = result?.lastLocation ?: return
138
+
139
+ onLocationChanged(location)
140
+ }
141
+
142
+ companion object {
143
+ const val DEFAULT_FASTEST_INTERVAL_MILLIS: Long = 1000
144
+ const val DEFAULT_INTERVAL_MILLIS: Long = 1000
145
+
146
+ const val LOG_TAG: String = "LocationManager"
147
+
148
+ private var INSTANCE: WeakReference<LocationManager?>? = null
149
+
150
+ @JvmStatic
151
+ fun getInstance(context: Context): LocationManager {
152
+ val appContext = context.applicationContext
153
+ INSTANCE?.get()?.let { return it }
154
+
155
+ synchronized(LocationManager::class.java) {
156
+ INSTANCE?.get()?.let { return it }
157
+
158
+ val created = LocationManager(appContext)
159
+ INSTANCE = WeakReference(created)
160
+
161
+ return created
162
+ }
163
+ }
164
+ }
165
+ }
@@ -8,7 +8,6 @@ object TrackUserLocationMode {
8
8
  const val HEADING: Int = 2
9
9
  const val COURSE: Int = 3
10
10
 
11
-
12
11
  @CameraMode.Mode
13
12
  fun getCameraMode(mode: Int): Int {
14
13
  return when (mode) {
@@ -0,0 +1,15 @@
1
+ package org.maplibre.reactnative.location
2
+
3
+ object TrackUserLocationState {
4
+ // The map view not yet tracked the user location
5
+ const val POSSIBLE: Int = 0
6
+
7
+ // The map view has begun to move to the first user location
8
+ const val BEGAN: Int = 1
9
+
10
+ // The map views begins a significant transition
11
+ const val SIGNIFICANT_TRANSITION: Int = 2
12
+
13
+ // The map view has finished moving to the user location
14
+ const val CHANGED: Int = 3
15
+ }
@@ -0,0 +1,40 @@
1
+ package org.maplibre.reactnative.location
2
+
3
+ import android.location.Location
4
+ import org.maplibre.android.geometry.LatLng
5
+
6
+ class UserLocation @JvmOverloads constructor(private var currentLocation: Location? = null) {
7
+ private var previousLocation: Location? = null
8
+
9
+ var trackingMode: Int = TrackUserLocationMode.NONE
10
+
11
+ fun getCurrentLocation(): Location? {
12
+ return currentLocation
13
+ }
14
+
15
+
16
+ val coordinate: LatLng?
17
+ get() {
18
+ if (currentLocation == null) {
19
+ return null
20
+ }
21
+
22
+ return LatLng(
23
+ currentLocation!!.getLatitude(), currentLocation!!.getLongitude()
24
+ )
25
+ }
26
+
27
+ val bearing: Double
28
+ get() {
29
+ if (currentLocation == null) {
30
+ return 0.0
31
+ }
32
+
33
+ return currentLocation!!.getBearing().toDouble()
34
+ }
35
+
36
+ fun setCurrentLocation(currentLocation: Location?) {
37
+ this.previousLocation = this.currentLocation
38
+ this.currentLocation = currentLocation
39
+ }
40
+ }
@@ -0,0 +1,18 @@
1
+ package org.maplibre.reactnative.location.engine
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import org.maplibre.android.location.engine.LocationEngine
6
+ import org.maplibre.android.location.engine.LocationEngineDefault.getDefaultLocationEngine
7
+
8
+ class DefaultLocationEngineProvider : LocationEngineProvidable {
9
+ override fun getLocationEngine(context: Context): LocationEngine {
10
+ val locationEngine = getDefaultLocationEngine(context.applicationContext)
11
+ Log.d(LOG_TAG, "DefaultLocationEngine will be used.")
12
+ return locationEngine
13
+ }
14
+
15
+ companion object {
16
+ private const val LOG_TAG = "DefaultLocationEngineProvider"
17
+ }
18
+ }
@@ -0,0 +1,8 @@
1
+ package org.maplibre.reactnative.location.engine
2
+
3
+ import android.content.Context
4
+ import org.maplibre.android.location.engine.LocationEngine
5
+
6
+ interface LocationEngineProvidable {
7
+ fun getLocationEngine(context: Context): LocationEngine
8
+ }
@@ -0,0 +1,153 @@
1
+ package org.maplibre.reactnative.modules
2
+
3
+ import android.Manifest
4
+ import android.location.Location
5
+ import android.os.Build
6
+ import androidx.annotation.RequiresPermission
7
+ import com.facebook.react.bridge.LifecycleEventListener
8
+ import com.facebook.react.bridge.Promise
9
+ import com.facebook.react.bridge.ReactApplicationContext
10
+ import com.facebook.react.bridge.WritableMap
11
+ import com.facebook.react.bridge.WritableNativeMap
12
+ import org.maplibre.android.location.engine.LocationEngineCallback
13
+ import org.maplibre.android.location.engine.LocationEngineResult
14
+ import org.maplibre.reactnative.NativeLocationModuleSpec
15
+ import org.maplibre.reactnative.location.LocationManager
16
+ import org.maplibre.reactnative.location.LocationManager.OnUserLocationChange
17
+
18
+ class MLRNLocationModule(reactContext: ReactApplicationContext) :
19
+ NativeLocationModuleSpec(reactContext) {
20
+ companion object {
21
+ const val NAME = "MLRNLocationModule"
22
+ }
23
+
24
+ override fun getName() = NAME
25
+
26
+ private var isEnabled = false
27
+ private var minDisplacement = 0f
28
+ private var isPaused = false
29
+
30
+ private val locationManager: LocationManager = LocationManager.getInstance(reactContext)
31
+
32
+ private val lifecycleEventListener: LifecycleEventListener = object : LifecycleEventListener {
33
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
34
+ override fun onHostResume() {
35
+ if (isEnabled) {
36
+ startLocationManager()
37
+ }
38
+ }
39
+
40
+ override fun onHostPause() {
41
+ pauseLocationManager()
42
+ }
43
+
44
+ override fun onHostDestroy() {
45
+ stopLocationManager()
46
+ }
47
+ }
48
+
49
+ private val onUserLocationChangeCallback: OnUserLocationChange = object : OnUserLocationChange {
50
+ override fun onLocationChange(location: Location) {
51
+ emitOnUpdate(locationToGeolocationPosition(location))
52
+ }
53
+ }
54
+
55
+ init {
56
+ reactContext.addLifecycleEventListener(lifecycleEventListener)
57
+ }
58
+
59
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
60
+ override fun start() {
61
+ isEnabled = true
62
+ startLocationManager()
63
+ }
64
+
65
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
66
+ override fun setMinDisplacement(minDisplacement: Double) {
67
+ if (this.minDisplacement == minDisplacement.toFloat()) return
68
+
69
+ this.minDisplacement = minDisplacement.toFloat()
70
+ if (isEnabled) {
71
+ locationManager.setMinDisplacement(this.minDisplacement)
72
+ locationManager.enable()
73
+ }
74
+ }
75
+
76
+ override fun stop() {
77
+ stopLocationManager()
78
+ }
79
+
80
+ fun pause() {
81
+ pauseLocationManager()
82
+ }
83
+
84
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
85
+ override fun getCurrentPosition(promise: Promise) {
86
+ locationManager.getLastKnownLocation(object :
87
+ LocationEngineCallback<LocationEngineResult?> {
88
+ override fun onSuccess(result: LocationEngineResult?) {
89
+ val location = result?.lastLocation
90
+
91
+ if (location != null) {
92
+ promise.resolve(locationToGeolocationPosition(location))
93
+ } else {
94
+ promise.resolve(null)
95
+ }
96
+ }
97
+
98
+ override fun onFailure(exception: Exception) {
99
+ promise.reject(exception)
100
+ }
101
+ })
102
+ }
103
+
104
+ @RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
105
+ private fun startLocationManager() {
106
+ locationManager.addLocationListener(onUserLocationChangeCallback)
107
+ locationManager.setMinDisplacement(minDisplacement)
108
+ locationManager.enable()
109
+ isPaused = false
110
+ }
111
+
112
+ private fun pauseLocationManager() {
113
+ if (isPaused) {
114
+ return
115
+ }
116
+
117
+ locationManager.disable()
118
+ isPaused = true
119
+ }
120
+
121
+ private fun stopLocationManager() {
122
+ if (!isEnabled) {
123
+ return
124
+ }
125
+
126
+ locationManager.removeLocationListener(onUserLocationChangeCallback)
127
+ locationManager.dispose()
128
+ isEnabled = false
129
+ isPaused = false
130
+ }
131
+
132
+ private fun locationToGeolocationPosition(location: Location): WritableMap {
133
+ val coords: WritableMap = WritableNativeMap()
134
+
135
+ coords.putDouble("longitude", location.longitude)
136
+ coords.putDouble("latitude", location.latitude)
137
+ coords.putDouble("altitude", location.altitude)
138
+ coords.putDouble("accuracy", location.accuracy.toDouble())
139
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
140
+ coords.putDouble("altitudeAccuracy", location.verticalAccuracyMeters.toDouble())
141
+ } else {
142
+ coords.putNull("altitudeAccuracy")
143
+ }
144
+ coords.putDouble("heading", location.bearing.toDouble())
145
+ coords.putDouble("speed", location.speed.toDouble())
146
+
147
+ val geolocationPosition: WritableMap = WritableNativeMap()
148
+ geolocationPosition.putMap("coords", coords)
149
+ geolocationPosition.putDouble("timestamp", location.time.toDouble())
150
+
151
+ return geolocationPosition
152
+ }
153
+ }
@@ -71,16 +71,11 @@ public class MLRNModule extends ReactContextBaseJavaModule {
71
71
  offlineModuleCallbackNames.put("Error", MLRNOfflineModule.OFFLINE_ERROR);
72
72
  offlineModuleCallbackNames.put("Progress", MLRNOfflineModule.OFFLINE_PROGRESS);
73
73
 
74
- // location module callback names
75
- Map<String, String> locationModuleCallbackNames = new HashMap<>();
76
- locationModuleCallbackNames.put("Update", MLRNLocationModule.LOCATION_UPDATE);
77
-
78
74
  return MapBuilder.<String, Object>builder()
79
75
  .put("StyleURL", styleURLS)
80
76
  .put("StyleSource", styleSourceConsts)
81
77
  .put("OfflinePackDownloadState", offlinePackDownloadStates)
82
78
  .put("OfflineCallbackName", offlineModuleCallbackNames)
83
- .put("LocationCallbackName", locationModuleCallbackNames)
84
79
  .build();
85
80
  }
86
81
 
@@ -0,0 +1,10 @@
1
+ package org.maplibre.reactnative.location.engine
2
+
3
+ import android.content.Context
4
+ import org.maplibre.android.location.engine.LocationEngine
5
+
6
+ class LocationEngineProvider : LocationEngineProvidable {
7
+ override fun getLocationEngine(context: Context): LocationEngine {
8
+ return DefaultLocationEngineProvider().getLocationEngine(context)
9
+ }
10
+ }