react-native-nitro-geolocation 0.1.0 → 0.1.1

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 (2) hide show
  1. package/README.md +251 -531
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,598 +1,318 @@
1
1
  # react-native-nitro-geolocation
2
2
 
3
- A high-performance geolocation library for React Native, powered by [Nitro Modules](https://github.com/mrousavy/nitro). This is a complete rewrite of `@react-native-community/geolocation` using modern architecture for superior performance and developer experience.
4
-
5
- ## Architecture Comparison
6
-
7
- ### Bridge vs JSI Architecture
8
-
9
- #### `@react-native-community/geolocation` (Old Bridge)
10
- ```
11
- ┌─────────────┐
12
- │ JS │
13
- └──────┬──────┘
14
- │ serialize JSON
15
-
16
- ┌─────────────┐
17
- │ Bridge │ ← Async message queue
18
- └──────┬──────┘
19
- │ deserialize JSON
20
-
21
- ┌─────────────┐
22
- │ Java/ObjC │
23
- └─────────────┘
24
- ```
25
-
26
- **Characteristics:**
27
- - **Asynchronous**: All calls go through message queue
28
- - **Serialization overhead**: Every data structure must be serialized/deserialized
29
- - **Event emitter pattern**: Uses `DeviceEventEmitter` for location updates
30
- - **Indirect callbacks**: Events broadcast to all JS listeners
31
-
32
- #### `react-native-nitro-geolocation` (Nitro/JSI)
33
- ```
34
- ┌─────────────┐
35
- │ JS │
36
- └──────┬──────┘
37
- │ direct memory access
38
-
39
- ┌─────────────┐
40
- │ C++ (JSI) │ ← Type-safe bindings
41
- └──────┬──────┘
42
- │ direct function call
43
-
44
- ┌─────────────┐
45
- │Kotlin/Swift │
46
- └─────────────┘
47
- ```
48
-
49
- **Characteristics:**
50
- - **Synchronous capable**: Direct C++ function calls (getCurrentPosition still async due to GPS)
51
- - **Zero serialization**: Shared memory between JS and native
52
- - **Direct callbacks**: Native directly invokes JS functions via JSI
53
- - **Type-safe**: Compile-time type checking in C++
3
+ [![NPM](https://img.shields.io/npm/v/react-native-nitro-geolocation)](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
+ ![react-native-nitro-geolocation)(https://raw.githubusercontent.com/jingjing2222/react-native-nitro-geolocation/main/demo.gif)
54
9
 
55
10
  ---
56
11
 
57
- ## Method-by-Method Architecture Analysis
58
-
59
- ### 1. `setRNConfiguration(config)`
60
-
61
- #### Original (`@react-native-community/geolocation`)
62
- ```java
63
- // GeolocationModule.java
64
- @ReactMethod
65
- public void setConfiguration(ReadableMap config) {
66
- mConfiguration = Configuration.fromReactMap(config);
67
- // Bridge automatically handles JSON deserialization
68
- }
69
- ```
70
-
71
- **Architecture:**
72
- - `@ReactMethod` annotation → Bridge registers method
73
- - `ReadableMap` → Deserialized from JS object
74
- - Configuration stored in Java object
75
-
76
- #### Nitro Version
77
- ```kotlin
78
- // NitroGeolocation.kt
79
- override fun setRNConfiguration(config: RNConfigurationInternal) {
80
- configuration = config
81
- }
82
- ```
83
-
84
- **Architecture:**
85
- - Direct C++ → Kotlin call via HybridObject
86
- - `RNConfigurationInternal` is C++ struct, no serialization
87
- - Type-safe: Compile error if structure changes
88
-
89
- **Performance Difference:**
90
- - **Bridge**: ~0.5-2ms (JSON parse + bridge overhead)
91
- - **Nitro**: ~0.01-0.05ms (direct memory copy)
92
- - **Speedup**: ~50-200x faster
12
+ ## 📘 Documentation
13
+
14
+ Full documentation available at:
15
+ 👉 [https://react-native-nitro-geolocation.pages.dev](https://react-native-nitro-geolocation.pages.dev)
93
16
 
94
17
  ---
95
18
 
96
- ### 2. `requestAuthorization(success, error)`
97
-
98
- #### Original Architecture
99
- ```java
100
- // GeolocationModule.java
101
- @ReactMethod
102
- public void requestAuthorization(final Callback success, final Callback error) {
103
- // Bridge wraps JS callbacks as Java Callback objects
104
- PermissionsModule.requestPermissions(..., new PromiseImpl(success, error));
105
- }
106
- ```
107
-
108
- **Call flow:**
109
- 1. JS calls method Bridge enqueues
110
- 2. Bridge deserializes callbacks → Creates Java `Callback` wrapper
111
- 3. Permission result `success.invoke()`
112
- 4. Bridge serializes result Enqueues back to JS
113
- 5. JS callback executed
114
-
115
- **Overhead per call**: ~1-3ms
116
-
117
- #### Nitro Architecture
118
- ```kotlin
119
- // NitroGeolocation.kt
120
- override fun requestAuthorization(
121
- success: (() -> Unit)?,
122
- error: ((error: GeolocationError) -> Unit)?
123
- ) {
124
- requestAuthorizationHandler.execute(success, error)
125
- }
126
- ```
127
-
128
- **Call flow:**
129
- 1. JS calls method → Direct C++ function call
130
- 2. C++ passes function references (no wrapping)
131
- 3. Permission result → `success?.invoke()`
132
- 4. JSI directly executes JS function (shared memory)
133
-
134
- **Overhead per call**: ~0.01-0.1ms
135
-
136
- **Key Difference:**
137
- - **Bridge**: Callbacks are serialized as IDs, invoked through message queue
138
- - **Nitro**: Callbacks are actual C++ function pointers to JS functions
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
139
60
 
140
61
  ---
141
62
 
142
- ### 3. `getCurrentPosition(success, error, options)`
143
-
144
- #### Original Architecture
145
- ```java
146
- // AndroidLocationManager.java
147
- public void getCurrentLocationData(ReadableMap options, Callback success, Callback error) {
148
- // Single callback instance for this request
149
- new SingleUpdateRequest(locationManager, provider, timeout, success, error).invoke(location);
150
- }
151
-
152
- private static class SingleUpdateRequest {
153
- private final Callback mSuccess;
154
- private final LocationListener mLocationListener = new LocationListener() {
155
- public void onLocationChanged(Location location) {
156
- mSuccess.invoke(locationToMap(location)); // Bridge serialization
157
- }
158
- };
159
- }
160
- ```
161
-
162
- **Data flow:**
163
- ```
164
- Android LocationManager
165
- → LocationListener.onLocationChanged(Location)
166
- → locationToMap(Location) // Create WritableMap
167
- → success.invoke(WritableMap) // Serialize to JSON
168
- → Bridge message queue
169
- → JS deserialize JSON
170
- → User callback
171
- ```
172
-
173
- **Overhead**: ~1-3ms per location update
174
-
175
- #### Nitro Architecture
176
- ```kotlin
177
- // GetCurrentPosition.kt
178
- fun execute(
179
- success: (position: GeolocationResponse) -> Unit,
180
- error: ((error: GeolocationError) -> Unit)?,
181
- options: GeolocationOptions?
182
- ) {
183
- val listener = object : LocationListener {
184
- override fun onLocationChanged(location: Location) {
185
- success(locationToPosition(location)) // Direct JSI call
186
- }
187
- }
188
- locationManager.requestLocationUpdates(provider, 100, 1f, listener, Looper.getMainLooper())
189
- }
190
- ```
191
-
192
- **Data flow:**
193
- ```
194
- Android LocationManager
195
- → LocationListener.onLocationChanged(Location)
196
- → locationToPosition(Location) // Create Kotlin data class
197
- → success(GeolocationResponse) // Direct JSI invocation
198
- → User callback (zero serialization)
199
- ```
200
-
201
- **Overhead**: ~0.01-0.1ms per location update
202
-
203
- **Additional Improvements:**
204
- 1. **Better location algorithm**: Implements `isBetterLocation()` from Android docs
205
- 2. **Modern API support**: Uses `getCurrentLocation()` API on Android 11+
206
- 3. **Timeout with fallback**: Returns last known location on timeout (configurable)
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
207
82
 
208
83
  ---
209
84
 
210
- ### 4. `watchPosition(success, error, options)`
211
-
212
- This is where architectural differences are most significant.
213
-
214
- #### Original Architecture
215
- ```java
216
- // AndroidLocationManager.java
217
- private final LocationListener mLocationListener = new LocationListener() {
218
- public void onLocationChanged(Location location) {
219
- // Broadcast to ALL JS listeners via event emitter
220
- mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
221
- .emit("geolocationDidChange", locationToMap(location));
222
- }
223
- };
224
-
225
- public void startObserving(ReadableMap options) {
226
- // Single global listener for ALL watches
227
- locationManager.requestLocationUpdates(provider, 1000, distanceFilter, mLocationListener);
228
- }
229
- ```
230
-
231
- **Architecture:**
232
- ```
233
- ┌──────────────────────────────┐
234
- │ Android LocationManager │
235
- └──────────────┬───────────────┘
236
- │ Single LocationListener
237
-
238
- ┌──────────────────────────────┐
239
- │ mLocationListener │
240
- └──────────────┬───────────────┘
241
- │ emit("geolocationDidChange", location)
242
-
243
- ┌──────────────────────────────┐
244
- │ DeviceEventEmitter │ ← Serialize location to JSON
245
- └──────────────┬───────────────┘
246
- │ Bridge
247
-
248
- ┌──────────────────────────────┐
249
- │ JS EventEmitter │
250
- └──────────────┬───────────────┘
251
- │ Broadcast to ALL listeners
252
- ├──────┬──────┬──────┐
253
- ▼ ▼ ▼ ▼
254
- watch1 watch2 watch3 watch4 (all receive same event)
255
- ```
256
-
257
- **Problems:**
258
- 1. **Single global listener**: Cannot have different options per watch
259
- 2. **Broadcast overhead**: All watches receive updates even if they have different filters
260
- 3. **JS-side filtering**: Each watch must filter events in JS
261
- 4. **Memory**: Event emitter maintains listener registry in JS
262
-
263
- **Data flow per update:**
264
- ```
265
- Location update (native)
266
- → serialize to JSON (1-2ms)
267
- → emit to bridge queue
268
- → deserialize in JS (1-2ms)
269
- → broadcast to N listeners (0.1ms × N)
270
- → each listener filters/processes
271
- Total: ~2-5ms + (0.1ms × N listeners)
272
- ```
273
-
274
- #### Nitro Architecture
275
- ```kotlin
276
- // WatchPosition.kt
277
- class WatchPosition(private val reactContext: ReactApplicationContext) {
278
- // Multiple watches, each with its own callback and options
279
- private val watchCallbacks = ConcurrentHashMap<Int, WatchCallback>()
280
- private val watchIdGenerator = AtomicInteger(0)
281
-
282
- data class WatchCallback(
283
- val success: (GeolocationResponse) -> Unit,
284
- val error: ((GeolocationError) -> Unit)?,
285
- val options: GeolocationOptions?
286
- )
287
-
288
- fun watch(success: ..., error: ..., options: ...): Int {
289
- val watchId = watchIdGenerator.incrementAndGet()
290
- watchCallbacks[watchId] = WatchCallback(success, error, options)
291
-
292
- // Start location updates only when first watch is added
293
- if (watchCallbacks.size == 1) {
294
- startObserving(options)
295
- }
296
- return watchId
297
- }
298
-
299
- private val locationListener = object : LocationListener {
300
- override fun onLocationChanged(location: Location) {
301
- val position = locationToPosition(location)
302
- // Direct callback to each watch
303
- watchCallbacks.values.forEach { callback ->
304
- callback.success(position)
305
- }
306
- }
307
- }
308
- }
309
- ```
310
-
311
- **Architecture:**
312
- ```
313
- ┌──────────────────────────────┐
314
- │ Android LocationManager │
315
- └──────────────┬───────────────┘
316
- │ Single LocationListener (lazy start)
317
-
318
- ┌──────────────────────────────┐
319
- │ locationListener │
320
- └──────────────┬───────────────┘
321
- │ Direct loop over watchCallbacks
322
- ├──────┬──────┬──────┐
323
- ▼ ▼ ▼ ▼
324
- watch1 watch2 watch3 watch4
325
- (direct JSI invocation to each callback)
326
- ```
327
-
328
- **Advantages:**
329
- 1. **Native watch management**: watchId and callbacks stored in native `ConcurrentHashMap`
330
- 2. **Direct callbacks**: Each watch callback invoked directly via JSI (no event emitter)
331
- 3. **Thread-safe**: `ConcurrentHashMap` + `AtomicInteger` for concurrent access
332
- 4. **Lazy lifecycle**: Start location updates on first watch, stop on last clearWatch
333
- 5. **Per-watch options**: Can support different options per watch (future enhancement)
334
-
335
- **Data flow per update:**
336
- ```
337
- Location update (native)
338
- → locationToPosition() (create Kotlin object, ~0.01ms)
339
- → forEach watch callback
340
- → Direct JSI call (0.01ms per watch)
341
- Total: ~0.01ms + (0.01ms × N watches)
342
- ```
343
-
344
- **Performance Comparison:**
345
-
346
- | Scenario | Bridge | Nitro | Speedup |
347
- |----------|--------|-------|---------|
348
- | 1 watch, 1 update/sec | ~3ms/update | ~0.02ms/update | **150x** |
349
- | 4 watches, 1 update/sec | ~5ms/update | ~0.05ms/update | **100x** |
350
- | 1 watch, 10 updates/sec | ~30ms/sec | ~0.2ms/sec | **150x** |
351
- | 4 watches, 10 updates/sec | ~50ms/sec | ~0.5ms/sec | **100x** |
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
+ ~~~
352
102
 
353
103
  ---
354
104
 
355
- ### 5. `clearWatch(watchId)`
356
-
357
- #### Original Architecture
358
- ```javascript
359
- // JS side (GeolocationModule wraps this)
360
- let watchID = 0;
361
- const subscriptions = new Map();
362
-
363
- function watchPosition(success, error, options) {
364
- const watchID = ++watchID;
365
- const subscription = DeviceEventEmitter.addListener('geolocationDidChange', success);
366
- subscriptions.set(watchID, subscription);
367
- return watchID;
368
- }
369
-
370
- function clearWatch(watchID) {
371
- const subscription = subscriptions.get(watchID);
372
- subscription?.remove(); // Removes JS listener only
373
- subscriptions.delete(watchID);
374
- }
375
- ```
376
-
377
- **Architecture:**
378
- - watchId managed in JS
379
- - No native call to `clearWatch()`
380
- - Native listener keeps running until `stopObserving()` called
381
-
382
- #### Nitro Architecture
383
- ```kotlin
384
- // WatchPosition.kt
385
- fun clearWatch(watchId: Int) {
386
- watchCallbacks.remove(watchId)
387
-
388
- // Automatically stop observing if no more watches
389
- if (watchCallbacks.isEmpty()) {
390
- stopObserving()
391
- }
392
- }
393
- ```
394
-
395
- **Architecture:**
396
- - watchId managed in native (Kotlin)
397
- - Direct removal from `ConcurrentHashMap`
398
- - Automatic cleanup: stops LocationManager when last watch removed
399
-
400
- **Key Difference:**
401
- - **Bridge**: JS-only cleanup, native keeps running
402
- - **Nitro**: Native cleanup + automatic resource management
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
+ ~~~
403
115
 
404
116
  ---
405
117
 
406
- ### 6. `stopObserving()`
407
-
408
- #### Original Architecture
409
- ```java
410
- // AndroidLocationManager.java
411
- public void stopObserving() {
412
- LocationManager locationManager = (LocationManager) mReactContext.getSystemService(Context.LOCATION_SERVICE);
413
- locationManager.removeUpdates(mLocationListener);
414
- mWatchedProvider = null;
415
- }
416
- ```
417
-
418
- - Single global listener removed
419
- - All watches stopped at once
420
- - No cleanup of watch callbacks (handled in JS)
421
-
422
- #### Nitro Architecture
423
- ```kotlin
424
- // WatchPosition.kt
425
- fun stopObserving() {
426
- val locationManager = reactContext.getSystemService(Context.LOCATION_SERVICE) as? LocationManager
427
-
428
- locationListener?.let { listener ->
429
- locationManager?.removeUpdates(listener)
430
- }
431
-
432
- // Complete cleanup
433
- locationListener = null
434
- watchedProvider = null
435
- currentOptions = null
436
- watchCallbacks.clear()
437
- }
438
- ```
439
-
440
- **Additional cleanup:**
441
- - All watch callbacks cleared from `ConcurrentHashMap`
442
- - Explicit null assignment for GC
443
- - Complete resource release
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
+ ~~~
444
132
 
445
133
  ---
446
134
 
447
- ## Overall Performance Summary
135
+ ### 4. Usage Example
448
136
 
449
- ### Latency Comparison
137
+ ~~~tsx
138
+ import Geolocation from 'react-native-nitro-geolocation';
450
139
 
451
- | Operation | Bridge Overhead | Nitro Overhead | Speedup |
452
- |-----------|----------------|----------------|---------|
453
- | Method call (e.g., setRNConfiguration) | 0.5-2ms | 0.01-0.05ms | **50-200x** |
454
- | Callback invocation | 1-3ms | 0.01-0.1ms | **30-100x** |
455
- | Location update (single) | 2-4ms | 0.02-0.15ms | **100-200x** |
456
- | Location update (4 watches) | 4-6ms | 0.05-0.4ms | **80-120x** |
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
+ ~~~
457
159
 
458
- ### Memory Comparison
160
+ ---
459
161
 
460
- | Component | Bridge | Nitro |
461
- |-----------|--------|-------|
462
- | Serialization buffers | ~1KB per call | 0 bytes (shared memory) |
463
- | Event emitter registry | ~100 bytes per listener | 0 bytes (no event emitter) |
464
- | Watch callback storage | JS Map (~50 bytes/watch) | ConcurrentHashMap (~40 bytes/watch) |
465
- | JSON parsing overhead | ~500 bytes per location | 0 bytes |
162
+ ### Migrating from `@react-native-community/geolocation`
466
163
 
467
- **Total memory savings**: ~2-5KB per active watch session
164
+ Nitro Geolocation is **100% API-compatible** with the original package.
165
+ You can migrate simply by replacing imports:
468
166
 
469
- ### Thread Safety
167
+ ~~~diff
168
+ - import Geolocation from '@react-native-community/geolocation';
169
+ + import Geolocation from 'react-native-nitro-geolocation';
170
+ ~~~
470
171
 
471
- | Aspect | Bridge | Nitro |
472
- |--------|--------|-------|
473
- | Concurrent watches | ✅ Handled by React Native bridge | ✅ ConcurrentHashMap + AtomicInteger |
474
- | Callback invocation | ⚠️ Queued (serialized execution) | ✅ Thread-safe direct invocation |
475
- | Resource cleanup | ⚠️ JS GC dependent | ✅ Explicit native cleanup |
172
+ **Benefits:**
173
+ - Better performance via JSI
174
+ - Reduced bridge overhead
175
+ - Improved permission consistency
176
+ - Built-in TypeScript definitions
476
177
 
477
178
  ---
478
179
 
479
- ## Battery Impact
480
-
481
- ### Bridge Architecture
482
- ```
483
- Location update (every 1s)
484
- ├─ GPS wakes CPU (~5mW)
485
- ├─ Serialize to JSON (~2mW for 2ms)
486
- ├─ Bridge context switch (~1mW)
487
- ├─ Deserialize in JS (~2mW for 2ms)
488
- └─ JS callback execution (~1mW)
489
- Total: ~11mW per update = 39.6J per hour
490
- ```
491
-
492
- ### Nitro Architecture
493
- ```
494
- Location update (every 1s)
495
- ├─ GPS wakes CPU (~5mW)
496
- ├─ Direct callback (~0.1mW for 0.02ms)
497
- └─ JS callback execution (~1mW)
498
- Total: ~6.1mW per update = 22J per hour
499
- ```
500
-
501
- **Battery savings**: ~45% less power consumption for continuous tracking
180
+ ## 🧠 API Methods
181
+
182
+ ### Summary
183
+ - `setRNConfiguration`
184
+ - `requestAuthorization`
185
+ - `getCurrentPosition`
186
+ - `watchPosition`
187
+ - `clearWatch`
188
+ - `stopObserving`
502
189
 
503
190
  ---
504
191
 
505
- ## Build Size Comparison
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
+ });
506
205
 
507
- | Component | Bridge | Nitro |
508
- |-----------|--------|-------|
509
- | Java/Kotlin code | ~15KB | ~18KB |
510
- | C++ code | 0KB | ~25KB (Nitro runtime) |
511
- | JavaScript | ~8KB | ~6KB (less event handling) |
512
- | **Total overhead** | ~23KB | ~49KB |
206
+ // recommended
207
+ import { setRNConfiguration } from 'react-native-nitro-geolocation';
513
208
 
514
- **Note**: Nitro adds ~26KB, but this is one-time cost shared across all Nitro modules in your app.
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)*
515
222
 
516
223
  ---
517
224
 
518
- ## Type Safety
225
+ ### `requestAuthorization()`
519
226
 
520
- ### Bridge (Runtime Type Checking)
521
- ```typescript
522
- // ❌ No compile-time safety
523
- getCurrentPosition(
524
- (position) => {
525
- console.log(position.coords.latitude); // Could be undefined at runtime
526
- }
527
- );
528
- ```
227
+ Requests location permission from the system.
529
228
 
530
- ### Nitro (Compile-Time Type Checking)
531
- ```typescript
532
- // ✅ Full TypeScript + C++ type safety
533
- getCurrentPosition(
534
- (position: GeolocationResponse) => {
535
- console.log(position.coords.latitude); // Guaranteed to exist
536
- }
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),
537
235
  );
538
- ```
539
236
 
540
- C++ generates type-safe bindings:
541
- ```cpp
542
- // Generated by Nitrogen
543
- struct GeolocationResponse {
544
- GeolocationCoordinates coords;
545
- double timestamp;
546
- };
547
- ```
237
+ // recommended
238
+ import { requestAuthorization } from 'react-native-nitro-geolocation';
548
239
 
549
- **Benefit**: Catch type errors at compile time, not in production.
240
+ requestAuthorization(
241
+ () => console.log('Permission granted'),
242
+ (error) => console.error('Permission error:', error),
243
+ );
244
+ ~~~
550
245
 
551
246
  ---
552
247
 
553
- ## Migration Guide
248
+ ### `getCurrentPosition()`
554
249
 
555
- Since this is a **drop-in replacement** for `@react-native-community/geolocation`, migration is trivial:
250
+ Retrieves the current device location once.
556
251
 
557
- ```diff
558
- - import Geolocation from '@react-native-community/geolocation';
559
- + import Geolocation from 'react-native-nitro-geolocation';
252
+ ~~~tsx
253
+ import Geolocation from 'react-native-nitro-geolocation';
560
254
 
561
- // API is 100% identical
562
- Geolocation.watchPosition(
563
- position => console.log(position),
564
- error => console.error(error),
565
- { enableHighAccuracy: true }
255
+ Geolocation.getCurrentPosition(
256
+ (position) => console.log(position),
257
+ (error) => console.error(error),
258
+ { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 },
566
259
  );
567
- ```
568
260
 
569
- **No code changes required!**
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
+ ~~~
570
270
 
571
271
  ---
572
272
 
573
- ## Why Choose Nitro Geolocation?
273
+ ### `watchPosition()`
574
274
 
575
- 1. **🚀 Performance**: 50-200x faster method calls, 100-200x faster location updates
576
- 2. **🔋 Battery**: ~45% less power consumption for continuous tracking
577
- 3. **🧵 Thread Safety**: Modern concurrent data structures (ConcurrentHashMap)
578
- 4. **🎯 Type Safety**: Compile-time type checking via C++
579
- 5. **🧹 Resource Management**: Automatic cleanup, explicit GC hints
580
- 6. **📦 Drop-in Replacement**: Zero migration cost
581
- 7. **🏗️ Modern Architecture**: JSI-based, ready for React Native's future
275
+ Watches location changes and calls the success callback each time.
582
276
 
583
- ---
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';
584
288
 
585
- ## Benchmarks
289
+ const id = watchPosition(
290
+ (position) => console.log('Position:', position),
291
+ (error) => console.error(error),
292
+ { interval: 5000, distanceFilter: 10 },
293
+ );
586
294
 
587
- See [BENCHMARKS.md](./BENCHMARKS.md) for detailed performance measurements.
295
+ ~~~
588
296
 
589
297
  ---
590
298
 
591
- ## License
299
+ ### `clearWatch()`
300
+
301
+ Stops watching location updates for a given watch ID.
592
302
 
593
- MIT
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
+ ---
594
313
 
595
- Original work Copyright (c) 2022-present, React Native Community
596
- Modified work Copyright (c) 2025, jingjing2222
314
+ ## 🧪 Summary
597
315
 
598
- This project is a Nitro Modules port of `@react-native-community/geolocation`.
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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-geolocation",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "⚡🚀Blazing-fast geolocation for React Native powered by Nitro Modules",
5
5
  "main": "src/index",
6
6
  "source": "src/index",