react-native-nitro-geolocation 0.1.1 โ 0.1.2
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.
- package/ios/LocationManager.swift +109 -124
- package/ios/NitroGeolocation.swift +10 -0
- package/package.json +2 -2
- package/README.md +0 -318
|
@@ -10,10 +10,11 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
private struct LocationRequest {
|
|
13
|
+
let id: UUID = UUID()
|
|
13
14
|
let success: (GeolocationResponse) -> Void
|
|
14
15
|
let error: ((GeolocationError) -> Void)?
|
|
15
16
|
let options: ParsedOptions
|
|
16
|
-
var timer:
|
|
17
|
+
var timer: DispatchSourceTimer?
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
private struct WatchSubscription {
|
|
@@ -22,7 +23,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
22
23
|
let options: ParsedOptions
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
struct ParsedOptions {
|
|
26
27
|
let timeout: Double
|
|
27
28
|
let maximumAge: Double
|
|
28
29
|
let accuracy: CLLocationAccuracy
|
|
@@ -51,7 +52,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
51
52
|
// MARK: - Properties
|
|
52
53
|
|
|
53
54
|
private var locationManager: CLLocationManager?
|
|
54
|
-
private var lastLocation: CLLocation?
|
|
55
|
+
internal private(set) var lastLocation: CLLocation?
|
|
55
56
|
private var usingSignificantChanges: Bool = false
|
|
56
57
|
|
|
57
58
|
// Authorization
|
|
@@ -84,36 +85,32 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
84
85
|
success: (() -> Void)?,
|
|
85
86
|
error: ((GeolocationError) -> Void)?
|
|
86
87
|
) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
self.initializeLocationManagerIfNeeded()
|
|
91
|
-
self.enqueueAuthorizationCallbacks(success: success, error: error)
|
|
92
|
-
|
|
93
|
-
// Skip permission requests if configured
|
|
94
|
-
if skipPermissionRequests {
|
|
95
|
-
if enableBackgroundLocationUpdates {
|
|
96
|
-
self.enableBackgroundLocationUpdatesIfNeeded()
|
|
97
|
-
}
|
|
98
|
-
self.handleAuthorizationSuccess()
|
|
99
|
-
return
|
|
100
|
-
}
|
|
88
|
+
initializeLocationManagerIfNeeded()
|
|
89
|
+
enqueueAuthorizationCallbacks(success: success, error: error)
|
|
101
90
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if
|
|
105
|
-
|
|
106
|
-
return
|
|
91
|
+
// Skip permission requests if configured
|
|
92
|
+
if skipPermissionRequests {
|
|
93
|
+
if enableBackgroundLocationUpdates {
|
|
94
|
+
enableBackgroundLocationUpdatesIfNeeded()
|
|
107
95
|
}
|
|
96
|
+
handleAuthorizationSuccess()
|
|
97
|
+
return
|
|
98
|
+
}
|
|
108
99
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
100
|
+
// Check if already authorized
|
|
101
|
+
let currentStatus = CLLocationManager.authorizationStatus()
|
|
102
|
+
if currentStatus == .authorizedAlways || currentStatus == .authorizedWhenInUse {
|
|
103
|
+
handleAuthorizationSuccess()
|
|
104
|
+
return
|
|
105
|
+
}
|
|
113
106
|
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
if currentStatus == .denied || currentStatus == .restricted {
|
|
108
|
+
handleAuthorizationError(for: currentStatus)
|
|
109
|
+
return
|
|
116
110
|
}
|
|
111
|
+
|
|
112
|
+
// Not determined yet, request permission
|
|
113
|
+
requestPermission(for: authType)
|
|
117
114
|
}
|
|
118
115
|
|
|
119
116
|
private func enqueueAuthorizationCallbacks(
|
|
@@ -153,63 +150,51 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
153
150
|
error: ((GeolocationError) -> Void)?,
|
|
154
151
|
options: GeolocationOptions?
|
|
155
152
|
) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
error?(self.createError(code: self.PERMISSION_DENIED, message: message))
|
|
169
|
-
return
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if !CLLocationManager.locationServicesEnabled() {
|
|
173
|
-
error?(
|
|
174
|
-
self.createError(
|
|
175
|
-
code: self.POSITION_UNAVAILABLE, message: "Location services disabled."))
|
|
176
|
-
return
|
|
177
|
-
}
|
|
153
|
+
let parsedOptions = ParsedOptions.parse(from: options)
|
|
154
|
+
|
|
155
|
+
// Check authorization
|
|
156
|
+
let status = CLLocationManager.authorizationStatus()
|
|
157
|
+
if status == .denied || status == .restricted {
|
|
158
|
+
let message =
|
|
159
|
+
status == .restricted
|
|
160
|
+
? "This application is not authorized to use location services"
|
|
161
|
+
: "User denied access to location services."
|
|
162
|
+
error?(createError(code: PERMISSION_DENIED, message: message))
|
|
163
|
+
return
|
|
164
|
+
}
|
|
178
165
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
success(self.locationToPosition(cached))
|
|
184
|
-
return
|
|
185
|
-
}
|
|
166
|
+
if !CLLocationManager.locationServicesEnabled() {
|
|
167
|
+
error?(createError(code: POSITION_UNAVAILABLE, message: "Location services disabled."))
|
|
168
|
+
return
|
|
169
|
+
}
|
|
186
170
|
|
|
187
|
-
|
|
171
|
+
initializeLocationManagerIfNeeded()
|
|
188
172
|
|
|
189
|
-
|
|
190
|
-
|
|
173
|
+
// Configure location manager
|
|
174
|
+
locationManager?.desiredAccuracy = parsedOptions.accuracy
|
|
175
|
+
locationManager?.distanceFilter = parsedOptions.distanceFilter
|
|
191
176
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
177
|
+
// Create request
|
|
178
|
+
var request = LocationRequest(
|
|
179
|
+
success: success,
|
|
180
|
+
error: error,
|
|
181
|
+
options: parsedOptions,
|
|
182
|
+
timer: nil
|
|
183
|
+
)
|
|
199
184
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
185
|
+
// Setup timeout with DispatchSourceTimer (no run loop needed)
|
|
186
|
+
let timer = DispatchSource.makeTimerSource(queue: .main)
|
|
187
|
+
timer.schedule(deadline: .now() + parsedOptions.timeout / 1000.0)
|
|
188
|
+
timer.setEventHandler { [weak self] in
|
|
189
|
+
self?.handleTimeout(for: request.id)
|
|
190
|
+
}
|
|
191
|
+
timer.resume()
|
|
192
|
+
request.timer = timer
|
|
207
193
|
|
|
208
|
-
|
|
194
|
+
pendingRequests.append(request)
|
|
209
195
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
}
|
|
196
|
+
// Start location updates
|
|
197
|
+
startMonitoring()
|
|
213
198
|
}
|
|
214
199
|
|
|
215
200
|
// MARK: - Watch Position
|
|
@@ -219,56 +204,44 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
219
204
|
error: ((GeolocationError) -> Void)?,
|
|
220
205
|
options: GeolocationOptions?
|
|
221
206
|
) -> Double {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
207
|
+
let parsedOptions = ParsedOptions.parse(from: options)
|
|
208
|
+
let watchId = nextWatchId
|
|
209
|
+
nextWatchId += 1
|
|
210
|
+
|
|
211
|
+
let subscription = WatchSubscription(
|
|
212
|
+
success: success,
|
|
213
|
+
error: error,
|
|
214
|
+
options: parsedOptions
|
|
215
|
+
)
|
|
230
216
|
|
|
231
|
-
|
|
232
|
-
success: success,
|
|
233
|
-
error: error,
|
|
234
|
-
options: parsedOptions
|
|
235
|
-
)
|
|
217
|
+
activeWatches[watchId] = subscription
|
|
236
218
|
|
|
237
|
-
|
|
219
|
+
initializeLocationManagerIfNeeded()
|
|
238
220
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
221
|
+
// Configure location manager
|
|
222
|
+
locationManager?.desiredAccuracy = parsedOptions.accuracy
|
|
223
|
+
locationManager?.distanceFilter = parsedOptions.distanceFilter
|
|
242
224
|
|
|
243
|
-
|
|
244
|
-
}
|
|
225
|
+
startMonitoring()
|
|
245
226
|
|
|
246
|
-
return
|
|
227
|
+
return watchId
|
|
247
228
|
}
|
|
248
229
|
|
|
249
230
|
func clearWatch(watchId: Double) {
|
|
250
|
-
|
|
251
|
-
guard let self = self else { return }
|
|
252
|
-
|
|
253
|
-
self.activeWatches.removeValue(forKey: watchId)
|
|
231
|
+
activeWatches.removeValue(forKey: watchId)
|
|
254
232
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
233
|
+
// Stop monitoring if no more watches or pending requests
|
|
234
|
+
if activeWatches.isEmpty && pendingRequests.isEmpty {
|
|
235
|
+
stopMonitoring()
|
|
259
236
|
}
|
|
260
237
|
}
|
|
261
238
|
|
|
262
239
|
func stopObserving() {
|
|
263
|
-
|
|
264
|
-
guard let self = self else { return }
|
|
240
|
+
activeWatches.removeAll()
|
|
265
241
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if self.pendingRequests.isEmpty {
|
|
270
|
-
self.stopMonitoring()
|
|
271
|
-
}
|
|
242
|
+
// Stop monitoring if no pending requests
|
|
243
|
+
if pendingRequests.isEmpty {
|
|
244
|
+
stopMonitoring()
|
|
272
245
|
}
|
|
273
246
|
}
|
|
274
247
|
|
|
@@ -298,7 +271,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
298
271
|
|
|
299
272
|
// 1. Fire all pending getCurrentPosition requests
|
|
300
273
|
for request in pendingRequests {
|
|
301
|
-
request.timer?.
|
|
274
|
+
request.timer?.cancel()
|
|
302
275
|
request.success(position)
|
|
303
276
|
}
|
|
304
277
|
pendingRequests.removeAll()
|
|
@@ -338,7 +311,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
338
311
|
|
|
339
312
|
// Fire all pending requests with error
|
|
340
313
|
for request in pendingRequests {
|
|
341
|
-
request.timer?.
|
|
314
|
+
request.timer?.cancel()
|
|
342
315
|
request.error?(geoError)
|
|
343
316
|
}
|
|
344
317
|
pendingRequests.removeAll()
|
|
@@ -355,8 +328,17 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
355
328
|
|
|
356
329
|
private func initializeLocationManagerIfNeeded() {
|
|
357
330
|
guard locationManager == nil else { return }
|
|
358
|
-
|
|
359
|
-
|
|
331
|
+
|
|
332
|
+
// CLLocationManager must be created on main thread for delegate callbacks
|
|
333
|
+
if Thread.isMainThread {
|
|
334
|
+
locationManager = CLLocationManager()
|
|
335
|
+
locationManager?.delegate = self
|
|
336
|
+
} else {
|
|
337
|
+
DispatchQueue.main.sync {
|
|
338
|
+
locationManager = CLLocationManager()
|
|
339
|
+
locationManager?.delegate = self
|
|
340
|
+
}
|
|
341
|
+
}
|
|
360
342
|
}
|
|
361
343
|
|
|
362
344
|
private func updateLocationManagerConfiguration() {
|
|
@@ -408,7 +390,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
408
390
|
}
|
|
409
391
|
}
|
|
410
392
|
|
|
411
|
-
|
|
393
|
+
func isCachedLocationValid(_ location: CLLocation, options: ParsedOptions) -> Bool {
|
|
412
394
|
// Check if maximumAge is infinity
|
|
413
395
|
if options.maximumAge.isInfinite {
|
|
414
396
|
return true
|
|
@@ -428,13 +410,16 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
428
410
|
return true
|
|
429
411
|
}
|
|
430
412
|
|
|
431
|
-
private func handleTimeout(for
|
|
432
|
-
// Find and remove the request with this
|
|
433
|
-
if let index = pendingRequests.firstIndex(where: { $0.
|
|
413
|
+
private func handleTimeout(for requestId: UUID) {
|
|
414
|
+
// Find and remove the request with this ID
|
|
415
|
+
if let index = pendingRequests.firstIndex(where: { $0.id == requestId }) {
|
|
434
416
|
let request = pendingRequests[index]
|
|
435
417
|
pendingRequests.remove(at: index)
|
|
436
418
|
|
|
437
|
-
//
|
|
419
|
+
// Cancel timer
|
|
420
|
+
request.timer?.cancel()
|
|
421
|
+
|
|
422
|
+
// Return timeout error
|
|
438
423
|
let timeoutSeconds = request.options.timeout / 1000.0
|
|
439
424
|
let message = String(format: "Unable to fetch location within %.1fs.", timeoutSeconds)
|
|
440
425
|
request.error?(createError(code: TIMEOUT, message: message))
|
|
@@ -493,7 +478,7 @@ class LocationManager: NSObject, CLLocationManagerDelegate {
|
|
|
493
478
|
queuedAuthorizationCallbacks.removeAll()
|
|
494
479
|
}
|
|
495
480
|
|
|
496
|
-
|
|
481
|
+
func locationToPosition(_ location: CLLocation) -> GeolocationResponse {
|
|
497
482
|
let altitude = location.verticalAccuracy < 0 ? 0.0 : location.altitude
|
|
498
483
|
let altitudeAccuracy = location.verticalAccuracy < 0 ? 0.0 : location.verticalAccuracy
|
|
499
484
|
let heading = location.course >= 0 ? location.course : -1.0
|
|
@@ -38,6 +38,16 @@ class NitroGeolocation: HybridNitroGeolocationSpec {
|
|
|
38
38
|
success: @escaping (GeolocationResponse) -> Void, error: ((GeolocationError) -> Void)?,
|
|
39
39
|
options: GeolocationOptions?
|
|
40
40
|
) throws {
|
|
41
|
+
// Fast path: check cached location immediately (no dispatch overhead!)
|
|
42
|
+
let parsedOptions = LocationManager.ParsedOptions.parse(from: options)
|
|
43
|
+
|
|
44
|
+
if let cached = locationManager.lastLocation,
|
|
45
|
+
locationManager.isCachedLocationValid(cached, options: parsedOptions) {
|
|
46
|
+
success(locationManager.locationToPosition(cached))
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Slow path: need GPS
|
|
41
51
|
locationManager.getCurrentPosition(success: success, error: error, options: options)
|
|
42
52
|
}
|
|
43
53
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-geolocation",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "โก๐Blazing-fast geolocation for React Native powered by Nitro Modules",
|
|
5
5
|
"main": "src/index",
|
|
6
6
|
"source": "src/index",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@types/react-test-renderer": "^18.0.0",
|
|
44
44
|
"react": "19.1.0",
|
|
45
45
|
"react-native": "0.81.1",
|
|
46
|
-
"react-native-nitro-modules": "^0.29.
|
|
46
|
+
"react-native-nitro-modules": "^0.29.6",
|
|
47
47
|
"typescript": "^5.9.3"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
package/README.md
DELETED
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
# react-native-nitro-geolocation
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/react-native-nitro-geolocation)
|
|
4
|
-
|
|
5
|
-
[`@react-native-community/geolocation`](https://github.com/michalchudziak/react-native-geolocation)
|
|
6
|
-
for the **React Native New Architecture** โ with 100% API compatibility.
|
|
7
|
-
|
|
8
|
-

|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## ๐งญ Introduction
|
|
20
|
-
|
|
21
|
-
The `@react-native-community/geolocation` package has long been the standard way to access device location in React Native apps.
|
|
22
|
-
|
|
23
|
-
With React Native moving toward **Nitro Modules**, **Fabric**, and **JSI**,
|
|
24
|
-
this project โ **React Native Nitro Geolocation** โ brings the same familiar API to the new architecture.
|
|
25
|
-
|
|
26
|
-
It provides the **same API surface** with:
|
|
27
|
-
|
|
28
|
-
- ๐ Faster performance via direct **JSI bindings**
|
|
29
|
-
- ๐ฑ Improved native consistency (Android + iOS)
|
|
30
|
-
- ๐ Seamless migration from `@react-native-community/geolocation`
|
|
31
|
-
- ๐งฉ TypeScript-first developer experience
|
|
32
|
-
- ๐ 100% API compatibility (drop-in replacement)
|
|
33
|
-
|
|
34
|
-
Whether upgrading an existing app or building a new one,
|
|
35
|
-
**React Native Nitro Geolocation** keeps the simplicity you know โ with modern internals.
|
|
36
|
-
|
|
37
|
-
## ๐ Architecture Comparison
|
|
38
|
-
|
|
39
|
-
### ๐งฉ Origin: Event-based Architecture (`@react-native-community/geolocation`)
|
|
40
|
-
|
|
41
|
-
~~~
|
|
42
|
-
JavaScript
|
|
43
|
-
โ EventEmitter.addListener('geolocationDidChange', callback)
|
|
44
|
-
โ (Callback stored in JS)
|
|
45
|
-
React Native Bridge (JSON serialization)
|
|
46
|
-
โ
|
|
47
|
-
Native Layer (Android/iOS)
|
|
48
|
-
โ LocationListener receives updates
|
|
49
|
-
โ emit('geolocationDidChange', data)
|
|
50
|
-
โ
|
|
51
|
-
EventEmitter dispatches to all listeners
|
|
52
|
-
โ
|
|
53
|
-
User callback executed
|
|
54
|
-
~~~
|
|
55
|
-
|
|
56
|
-
**Key traits:**
|
|
57
|
-
- Callbacks stored only in JS
|
|
58
|
-
- Bridge serialization on every update
|
|
59
|
-
- One shared event stream
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
### โก Modern: Direct Callback Architecture (`react-native-nitro-geolocation`)
|
|
64
|
-
|
|
65
|
-
~~~
|
|
66
|
-
JavaScript
|
|
67
|
-
โ Geolocation.watchPosition(success, error)
|
|
68
|
-
โ (Callbacks passed directly to native via JSI)
|
|
69
|
-
JSI Layer (No Bridge!)
|
|
70
|
-
โ
|
|
71
|
-
Native Layer (Kotlin/Swift)
|
|
72
|
-
โ callback.success(position) โ JSI direct call
|
|
73
|
-
โ
|
|
74
|
-
User callback executed immediately
|
|
75
|
-
~~~
|
|
76
|
-
|
|
77
|
-
**Key traits:**
|
|
78
|
-
- Callbacks passed as native JSI references
|
|
79
|
-
- No Bridge serialization
|
|
80
|
-
- Independent callback per watcher
|
|
81
|
-
- Native โ JS communication in real time
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## โก Quick Start
|
|
86
|
-
|
|
87
|
-
### 1. Installation
|
|
88
|
-
|
|
89
|
-
~~~bash
|
|
90
|
-
# Install Nitro core and Geolocation module
|
|
91
|
-
yarn add react-native-nitro-modules react-native-nitro-geolocation
|
|
92
|
-
|
|
93
|
-
# or using npm
|
|
94
|
-
npm install react-native-nitro-modules react-native-nitro-geolocation
|
|
95
|
-
~~~
|
|
96
|
-
|
|
97
|
-
After installation, rebuild your native app:
|
|
98
|
-
|
|
99
|
-
~~~bash
|
|
100
|
-
cd ios && pod install
|
|
101
|
-
~~~
|
|
102
|
-
|
|
103
|
-
---
|
|
104
|
-
|
|
105
|
-
### 2. iOS Setup
|
|
106
|
-
|
|
107
|
-
Add the following permissions to your **Info.plist**:
|
|
108
|
-
|
|
109
|
-
~~~xml
|
|
110
|
-
<key>NSLocationWhenInUseUsageDescription</key>
|
|
111
|
-
<string>This app requires access to your location while itโs in use.</string>
|
|
112
|
-
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
|
113
|
-
<string>This app requires access to your location at all times.</string>
|
|
114
|
-
~~~
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
### 3. Android Setup
|
|
119
|
-
|
|
120
|
-
Add these permissions to your **AndroidManifest.xml**:
|
|
121
|
-
|
|
122
|
-
~~~xml
|
|
123
|
-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
124
|
-
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
125
|
-
~~~
|
|
126
|
-
|
|
127
|
-
Optional (for background access):
|
|
128
|
-
|
|
129
|
-
~~~xml
|
|
130
|
-
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
|
131
|
-
~~~
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
### 4. Usage Example
|
|
136
|
-
|
|
137
|
-
~~~tsx
|
|
138
|
-
import Geolocation from 'react-native-nitro-geolocation';
|
|
139
|
-
|
|
140
|
-
Geolocation.getCurrentPosition(
|
|
141
|
-
(position) => {
|
|
142
|
-
console.log('Latitude:', position.coords.latitude);
|
|
143
|
-
console.log('Longitude:', position.coords.longitude);
|
|
144
|
-
},
|
|
145
|
-
(error) => {
|
|
146
|
-
console.error('Location error:', error);
|
|
147
|
-
},
|
|
148
|
-
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
// Subscribe to continuous updates
|
|
152
|
-
const watchId = Geolocation.watchPosition(
|
|
153
|
-
(position) => {
|
|
154
|
-
console.log('Updated position:', position);
|
|
155
|
-
},
|
|
156
|
-
(error) => console.error(error),
|
|
157
|
-
);
|
|
158
|
-
~~~
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
### Migrating from `@react-native-community/geolocation`
|
|
163
|
-
|
|
164
|
-
Nitro Geolocation is **100% API-compatible** with the original package.
|
|
165
|
-
You can migrate simply by replacing imports:
|
|
166
|
-
|
|
167
|
-
~~~diff
|
|
168
|
-
- import Geolocation from '@react-native-community/geolocation';
|
|
169
|
-
+ import Geolocation from 'react-native-nitro-geolocation';
|
|
170
|
-
~~~
|
|
171
|
-
|
|
172
|
-
**Benefits:**
|
|
173
|
-
- Better performance via JSI
|
|
174
|
-
- Reduced bridge overhead
|
|
175
|
-
- Improved permission consistency
|
|
176
|
-
- Built-in TypeScript definitions
|
|
177
|
-
|
|
178
|
-
---
|
|
179
|
-
|
|
180
|
-
## ๐ง API Methods
|
|
181
|
-
|
|
182
|
-
### Summary
|
|
183
|
-
- `setRNConfiguration`
|
|
184
|
-
- `requestAuthorization`
|
|
185
|
-
- `getCurrentPosition`
|
|
186
|
-
- `watchPosition`
|
|
187
|
-
- `clearWatch`
|
|
188
|
-
- `stopObserving`
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
### `setRNConfiguration()`
|
|
193
|
-
|
|
194
|
-
Sets configuration options used for all location requests.
|
|
195
|
-
|
|
196
|
-
~~~tsx
|
|
197
|
-
import Geolocation from 'react-native-nitro-geolocation';
|
|
198
|
-
|
|
199
|
-
Geolocation.setRNConfiguration({
|
|
200
|
-
skipPermissionRequests: false,
|
|
201
|
-
authorizationLevel: 'auto',
|
|
202
|
-
enableBackgroundLocationUpdates: true,
|
|
203
|
-
locationProvider: 'auto',
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
// recommended
|
|
207
|
-
import { setRNConfiguration } from 'react-native-nitro-geolocation';
|
|
208
|
-
|
|
209
|
-
setRNConfiguration({
|
|
210
|
-
skipPermissionRequests: false,
|
|
211
|
-
authorizationLevel: 'auto',
|
|
212
|
-
enableBackgroundLocationUpdates: true,
|
|
213
|
-
locationProvider: 'auto',
|
|
214
|
-
});
|
|
215
|
-
~~~
|
|
216
|
-
|
|
217
|
-
**Options:**
|
|
218
|
-
- `skipPermissionRequests` โ default `false`
|
|
219
|
-
- `authorizationLevel` โ `'always' | 'whenInUse' | 'auto'` *(iOS only)*
|
|
220
|
-
- `enableBackgroundLocationUpdates` โ *(iOS only)*
|
|
221
|
-
- `locationProvider` โ `'playServices' | 'android' | 'auto'` *(Android only)*
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
### `requestAuthorization()`
|
|
226
|
-
|
|
227
|
-
Requests location permission from the system.
|
|
228
|
-
|
|
229
|
-
~~~tsx
|
|
230
|
-
import Geolocation from 'react-native-nitro-geolocation';
|
|
231
|
-
|
|
232
|
-
Geolocation.requestAuthorization(
|
|
233
|
-
() => console.log('Permission granted'),
|
|
234
|
-
(error) => console.error('Permission error:', error),
|
|
235
|
-
);
|
|
236
|
-
|
|
237
|
-
// recommended
|
|
238
|
-
import { requestAuthorization } from 'react-native-nitro-geolocation';
|
|
239
|
-
|
|
240
|
-
requestAuthorization(
|
|
241
|
-
() => console.log('Permission granted'),
|
|
242
|
-
(error) => console.error('Permission error:', error),
|
|
243
|
-
);
|
|
244
|
-
~~~
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
### `getCurrentPosition()`
|
|
249
|
-
|
|
250
|
-
Retrieves the current device location once.
|
|
251
|
-
|
|
252
|
-
~~~tsx
|
|
253
|
-
import Geolocation from 'react-native-nitro-geolocation';
|
|
254
|
-
|
|
255
|
-
Geolocation.getCurrentPosition(
|
|
256
|
-
(position) => console.log(position),
|
|
257
|
-
(error) => console.error(error),
|
|
258
|
-
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 },
|
|
259
|
-
);
|
|
260
|
-
|
|
261
|
-
// recommended
|
|
262
|
-
import { getCurrentPosition } from 'react-native-nitro-geolocation';
|
|
263
|
-
|
|
264
|
-
getCurrentPosition(
|
|
265
|
-
(position) => console.log(position),
|
|
266
|
-
(error) => console.error(error),
|
|
267
|
-
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 },
|
|
268
|
-
);
|
|
269
|
-
~~~
|
|
270
|
-
|
|
271
|
-
---
|
|
272
|
-
|
|
273
|
-
### `watchPosition()`
|
|
274
|
-
|
|
275
|
-
Watches location changes and calls the success callback each time.
|
|
276
|
-
|
|
277
|
-
~~~tsx
|
|
278
|
-
import Geolocation from 'react-native-nitro-geolocation';
|
|
279
|
-
|
|
280
|
-
const id = Geolocation.watchPosition(
|
|
281
|
-
(position) => console.log('Position:', position),
|
|
282
|
-
(error) => console.error(error),
|
|
283
|
-
{ interval: 5000, distanceFilter: 10 },
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
// recommended
|
|
287
|
-
import { watchPosition } from 'react-native-nitro-geolocation';
|
|
288
|
-
|
|
289
|
-
const id = watchPosition(
|
|
290
|
-
(position) => console.log('Position:', position),
|
|
291
|
-
(error) => console.error(error),
|
|
292
|
-
{ interval: 5000, distanceFilter: 10 },
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
~~~
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
### `clearWatch()`
|
|
300
|
-
|
|
301
|
-
Stops watching location updates for a given watch ID.
|
|
302
|
-
|
|
303
|
-
~~~tsx
|
|
304
|
-
import Geolocation from 'react-native-nitro-geolocation';
|
|
305
|
-
Geolocation.clearWatch(id);
|
|
306
|
-
|
|
307
|
-
// recommended
|
|
308
|
-
import { clearWatch } from 'react-native-nitro-geolocation';
|
|
309
|
-
clearWatch(id);
|
|
310
|
-
~~~
|
|
311
|
-
|
|
312
|
-
---
|
|
313
|
-
|
|
314
|
-
## ๐งช Summary
|
|
315
|
-
|
|
316
|
-
**React Native Nitro Geolocation** transforms the geolocation API
|
|
317
|
-
from a bridge-based, event-driven system into a **JSI-powered direct-callback model** โ
|
|
318
|
-
delivering native-level performance with **zero API changes** for developers.
|