react-native-nitro-geolocation 0.1.2 → 0.3.0

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 (127) hide show
  1. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/GetCurrentPosition.kt +4 -4
  2. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocation.kt +642 -50
  3. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocationCompat.kt +81 -0
  4. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/WatchPosition.kt +4 -4
  5. package/ios/LocationManager.swift +4 -4
  6. package/ios/NitroGeolocation.swift +543 -68
  7. package/ios/NitroGeolocationCompat.swift +109 -0
  8. package/nitrogen/generated/android/c++/JAuthorizationLevel.hpp +61 -0
  9. package/nitrogen/generated/android/c++/JAuthorizationLevelInternal.hpp +3 -4
  10. package/nitrogen/generated/android/c++/JFunc_void.hpp +2 -1
  11. package/nitrogen/generated/android/c++/JFunc_void_GeolocationError.hpp +2 -1
  12. package/nitrogen/generated/android/c++/JFunc_void_GeolocationResponse.hpp +6 -1
  13. package/nitrogen/generated/android/c++/JFunc_void_LocationError.hpp +78 -0
  14. package/nitrogen/generated/android/c++/JGeolocationCoordinates.hpp +25 -17
  15. package/nitrogen/generated/android/c++/JGeolocationError.hpp +5 -1
  16. package/nitrogen/generated/android/c++/JGeolocationOptions.hpp +5 -1
  17. package/nitrogen/generated/android/c++/JGeolocationResponse.hpp +9 -1
  18. package/nitrogen/generated/android/c++/JHybridNitroGeolocationCompatSpec.cpp +109 -0
  19. package/nitrogen/generated/android/c++/JHybridNitroGeolocationCompatSpec.hpp +70 -0
  20. package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.cpp +98 -42
  21. package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.hpp +7 -5
  22. package/nitrogen/generated/android/c++/JLocationError.hpp +61 -0
  23. package/nitrogen/generated/android/c++/JLocationProvider.hpp +61 -0
  24. package/nitrogen/generated/android/c++/JLocationProviderInternal.hpp +3 -4
  25. package/nitrogen/generated/android/c++/JLocationRequestOptions.hpp +81 -0
  26. package/nitrogen/generated/android/c++/JModernGeolocationConfiguration.hpp +73 -0
  27. package/nitrogen/generated/android/c++/JNullableDouble.cpp +26 -0
  28. package/nitrogen/generated/android/c++/JNullableDouble.hpp +69 -0
  29. package/nitrogen/generated/android/c++/JPermissionStatus.hpp +64 -0
  30. package/nitrogen/generated/android/c++/JRNConfigurationInternal.hpp +5 -1
  31. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AuthorizationLevel.kt +24 -0
  32. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AuthorizationLevelInternal.kt +2 -0
  33. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void.kt +0 -1
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_GeolocationError.kt +0 -1
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_GeolocationResponse.kt +0 -1
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_LocationError.kt +80 -0
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationCoordinates.kt +34 -25
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationError.kt +27 -18
  39. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationOptions.kt +33 -24
  40. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationResponse.kt +18 -9
  41. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationCompatSpec.kt +92 -0
  42. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationSpec.kt +17 -17
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationError.kt +41 -0
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProvider.kt +24 -0
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderInternal.kt +2 -0
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationRequestOptions.kt +56 -0
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/ModernGeolocationConfiguration.kt +47 -0
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/NullableDouble.kt +59 -0
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/PermissionStatus.kt +25 -0
  50. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/RNConfigurationInternal.kt +24 -15
  51. package/nitrogen/generated/android/nitrogeolocation+autolinking.cmake +3 -0
  52. package/nitrogen/generated/android/nitrogeolocationOnLoad.cpp +14 -2
  53. package/nitrogen/generated/ios/NitroGeolocation+autolinking.rb +1 -1
  54. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.cpp +55 -13
  55. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.hpp +325 -68
  56. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Umbrella.hpp +26 -0
  57. package/nitrogen/generated/ios/NitroGeolocationAutolinking.mm +8 -0
  58. package/nitrogen/generated/ios/NitroGeolocationAutolinking.swift +15 -0
  59. package/nitrogen/generated/ios/c++/HybridNitroGeolocationCompatSpecSwift.cpp +11 -0
  60. package/nitrogen/generated/ios/c++/HybridNitroGeolocationCompatSpecSwift.hpp +130 -0
  61. package/nitrogen/generated/ios/c++/HybridNitroGeolocationSpecSwift.hpp +47 -26
  62. package/nitrogen/generated/ios/swift/AuthorizationLevel.swift +44 -0
  63. package/nitrogen/generated/ios/swift/Func_void.swift +1 -1
  64. package/nitrogen/generated/ios/swift/Func_void_GeolocationError.swift +1 -1
  65. package/nitrogen/generated/ios/swift/Func_void_GeolocationResponse.swift +1 -1
  66. package/nitrogen/generated/ios/swift/Func_void_LocationError.swift +47 -0
  67. package/nitrogen/generated/ios/swift/Func_void_PermissionStatus.swift +47 -0
  68. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  69. package/nitrogen/generated/ios/swift/GeolocationCoordinates.swift +132 -93
  70. package/nitrogen/generated/ios/swift/GeolocationError.swift +11 -40
  71. package/nitrogen/generated/ios/swift/GeolocationOptions.swift +29 -98
  72. package/nitrogen/generated/ios/swift/GeolocationResponse.swift +5 -16
  73. package/nitrogen/generated/ios/swift/HybridNitroGeolocationCompatSpec.swift +61 -0
  74. package/nitrogen/generated/ios/swift/HybridNitroGeolocationCompatSpec_cxx.swift +244 -0
  75. package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec.swift +13 -5
  76. package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec_cxx.swift +66 -64
  77. package/nitrogen/generated/ios/swift/LocationError.swift +35 -0
  78. package/nitrogen/generated/ios/swift/LocationProvider.swift +44 -0
  79. package/nitrogen/generated/ios/swift/LocationRequestOptions.swift +116 -0
  80. package/nitrogen/generated/ios/swift/ModernGeolocationConfiguration.swift +83 -0
  81. package/nitrogen/generated/ios/swift/NullableDouble.swift +18 -0
  82. package/nitrogen/generated/ios/swift/PermissionStatus.swift +48 -0
  83. package/nitrogen/generated/ios/swift/RNConfigurationInternal.swift +16 -50
  84. package/nitrogen/generated/shared/c++/AuthorizationLevel.hpp +80 -0
  85. package/nitrogen/generated/shared/c++/GeolocationCoordinates.hpp +45 -27
  86. package/nitrogen/generated/shared/c++/GeolocationError.hpp +32 -16
  87. package/nitrogen/generated/shared/c++/GeolocationOptions.hpp +38 -22
  88. package/nitrogen/generated/shared/c++/GeolocationResponse.hpp +23 -7
  89. package/nitrogen/generated/shared/c++/HybridNitroGeolocationCompatSpec.cpp +26 -0
  90. package/nitrogen/generated/shared/c++/HybridNitroGeolocationCompatSpec.hpp +79 -0
  91. package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.cpp +4 -3
  92. package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.hpp +22 -16
  93. package/nitrogen/generated/shared/c++/LocationError.hpp +87 -0
  94. package/nitrogen/generated/shared/c++/LocationProvider.hpp +80 -0
  95. package/nitrogen/generated/shared/c++/LocationRequestOptions.hpp +107 -0
  96. package/nitrogen/generated/shared/c++/ModernGeolocationConfiguration.hpp +100 -0
  97. package/nitrogen/generated/shared/c++/PermissionStatus.hpp +84 -0
  98. package/nitrogen/generated/shared/c++/RNConfigurationInternal.hpp +29 -13
  99. package/package.json +16 -7
  100. package/src/GeolocationClient.ts +116 -0
  101. package/src/NitroGeolocation.nitro.ts +177 -30
  102. package/src/NitroGeolocationCompat.nitro.ts +41 -0
  103. package/src/NitroGeolocationModule.ts +6 -0
  104. package/src/compat/clearWatch.ts +9 -0
  105. package/src/{getCurrentPosition.ts → compat/getCurrentPosition.ts} +7 -3
  106. package/src/compat/index.tsx +34 -0
  107. package/src/compat/requestAuthorization.ts +9 -0
  108. package/src/{setRNConfiguration.ts → compat/setRNConfiguration.ts} +6 -4
  109. package/src/{stopObserving.ts → compat/stopObserving.ts} +4 -2
  110. package/src/{watchPosition.ts → compat/watchPosition.ts} +7 -6
  111. package/src/components/GeolocationProvider.tsx +91 -0
  112. package/src/components/index.ts +13 -0
  113. package/src/hooks/index.ts +9 -0
  114. package/src/hooks/useCheckPermission.ts +46 -0
  115. package/src/hooks/useGetCurrentPosition.ts +140 -0
  116. package/src/hooks/useRequestPermission.ts +98 -0
  117. package/src/hooks/useWatchPosition.ts +130 -0
  118. package/src/index.tsx +72 -27
  119. package/src/types.ts +32 -4
  120. package/src/utils/cache.ts +25 -0
  121. package/src/utils/config.ts +93 -0
  122. package/src/utils/errors.ts +82 -0
  123. package/src/utils/index.ts +27 -0
  124. package/src/utils/provider.ts +61 -0
  125. package/src/utils/quality.ts +98 -0
  126. package/src/clearWatch.ts +0 -13
  127. package/src/requestAuthorization.ts +0 -9
package/src/index.tsx CHANGED
@@ -1,34 +1,79 @@
1
- // Export methods
2
- export { clearWatch } from "./clearWatch";
3
- export { getCurrentPosition } from "./getCurrentPosition";
4
- export { requestAuthorization } from "./requestAuthorization";
5
- export { setRNConfiguration } from "./setRNConfiguration";
6
- export { stopObserving } from "./stopObserving";
7
- export { watchPosition } from "./watchPosition";
1
+ /**
2
+ * Modern Geolocation API for React Native.
3
+ *
4
+ * This is the main entry point for the modern, React-friendly API.
5
+ * For legacy compatibility, use: import Geolocation from 'react-native-nitro-geolocation/compat'
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * import {
10
+ * GeolocationClient,
11
+ * GeolocationClientProvider,
12
+ * useRequestPermission,
13
+ * useGetCurrentPosition,
14
+ * useWatchPosition
15
+ * } from 'react-native-nitro-geolocation';
16
+ *
17
+ * // Create GeolocationClient instance
18
+ * const geolocationClient = new GeolocationClient({
19
+ * authorizationLevel: 'whenInUse',
20
+ * enableBackgroundLocationUpdates: false,
21
+ * locationProvider: 'auto'
22
+ * });
23
+ *
24
+ * function App() {
25
+ * return (
26
+ * <GeolocationClientProvider client={geolocationClient}>
27
+ * <YourApp />
28
+ * </GeolocationClientProvider>
29
+ * );
30
+ * }
31
+ *
32
+ * function LocationButton() {
33
+ * const { getCurrentPosition } = useGetCurrentPosition();
34
+ * const [loading, setLoading] = useState(false);
35
+ *
36
+ * const handlePress = async () => {
37
+ * setLoading(true);
38
+ * try {
39
+ * const pos = await getCurrentPosition({ enableHighAccuracy: true });
40
+ * console.log('Position:', pos);
41
+ * } catch (error) {
42
+ * console.error('Error:', error);
43
+ * } finally {
44
+ * setLoading(false);
45
+ * }
46
+ * };
47
+ *
48
+ * return <Button onPress={handlePress} disabled={loading} />;
49
+ * }
50
+ * ```
51
+ */
8
52
 
9
- // Default export for compatibility
10
- import { clearWatch } from "./clearWatch";
11
- import { getCurrentPosition } from "./getCurrentPosition";
12
- import { requestAuthorization } from "./requestAuthorization";
13
- import { setRNConfiguration } from "./setRNConfiguration";
14
- import { stopObserving } from "./stopObserving";
15
- import { watchPosition } from "./watchPosition";
53
+ // Core
54
+ export { GeolocationClient } from "./GeolocationClient";
55
+ export type { GeolocationClientConfig } from "./GeolocationClient";
16
56
 
17
- const Geolocation = {
18
- setRNConfiguration,
19
- requestAuthorization,
20
- getCurrentPosition,
21
- watchPosition,
22
- clearWatch,
23
- stopObserving
24
- };
57
+ // Components
58
+ export * from "./components";
59
+
60
+ // Hooks
61
+ export * from "./hooks";
62
+
63
+ // Types from Nitro spec
64
+ export type {
65
+ PermissionStatus,
66
+ LocationRequestOptions,
67
+ LocationError
68
+ } from "./NitroGeolocation.nitro";
25
69
 
26
- // Export types
27
70
  export type {
28
- GeolocationConfiguration,
29
71
  GeolocationResponse,
30
- GeolocationError,
31
- GeolocationOptions
72
+ GeolocationCoordinates,
73
+ AuthorizationLevel,
74
+ LocationProvider,
75
+ ModernGeolocationConfiguration
32
76
  } from "./types";
33
77
 
34
- export default Geolocation;
78
+ // Pure utility functions (advanced users only)
79
+ export * from "./utils";
package/src/types.ts CHANGED
@@ -1,6 +1,34 @@
1
1
  // Public API types (compatible with @react-native-community/geolocation)
2
2
  export type AuthorizationLevel = "always" | "whenInUse" | "auto";
3
3
  export type LocationProvider = "playServices" | "android" | "auto";
4
+ export type NullableDouble = number | null;
5
+
6
+ /**
7
+ * User-facing geolocation configuration.
8
+ * This uses "android" instead of "android_platform" for better DX.
9
+ */
10
+ export interface ModernGeolocationConfiguration {
11
+ /**
12
+ * Automatically request location permission when GeolocationProvider mounts.
13
+ * @default false
14
+ */
15
+ autoRequestPermission?: boolean;
16
+
17
+ /**
18
+ * iOS: Authorization level
19
+ */
20
+ authorizationLevel?: AuthorizationLevel;
21
+
22
+ /**
23
+ * iOS: Enable background location updates.
24
+ */
25
+ enableBackgroundLocationUpdates?: boolean;
26
+
27
+ /**
28
+ * Android: Location provider
29
+ */
30
+ locationProvider?: LocationProvider;
31
+ }
4
32
 
5
33
  export interface GeolocationConfiguration {
6
34
  skipPermissionRequests: boolean;
@@ -12,11 +40,11 @@ export interface GeolocationConfiguration {
12
40
  export interface GeolocationCoordinates {
13
41
  latitude: number;
14
42
  longitude: number;
15
- altitude: number | null;
43
+ altitude: NullableDouble;
16
44
  accuracy: number;
17
- altitudeAccuracy: number | null;
18
- heading: number | null;
19
- speed: number | null;
45
+ altitudeAccuracy: NullableDouble;
46
+ heading: NullableDouble;
47
+ speed: NullableDouble;
20
48
  }
21
49
 
22
50
  export interface GeolocationResponse {
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Validates whether a cached location is still fresh based on its age.
3
+ *
4
+ * @param timestampMs - The timestamp of the cached location (in milliseconds)
5
+ * @param currentTimeMs - The current time (in milliseconds)
6
+ * @param maximumAgeMs - The maximum age allowed for the cache (in milliseconds)
7
+ * @returns true if the cache is still valid, false otherwise
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const timestampMs = Date.now() - 5000; // 5 seconds ago
12
+ * const currentTimeMs = Date.now();
13
+ * const maximumAgeMs = 10000; // 10 seconds
14
+ *
15
+ * isCachedLocationValid(timestampMs, currentTimeMs, maximumAgeMs); // true
16
+ * ```
17
+ */
18
+ export function isCachedLocationValid(
19
+ timestampMs: number,
20
+ currentTimeMs: number,
21
+ maximumAgeMs: number
22
+ ): boolean {
23
+ const age = currentTimeMs - timestampMs;
24
+ return age < maximumAgeMs;
25
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Represents a location request with its configuration options.
3
+ */
4
+ export interface LocationRequest {
5
+ /** Whether high accuracy mode is enabled */
6
+ enableHighAccuracy: boolean;
7
+ /** Minimum distance change (in meters) for updates */
8
+ distanceFilter: number;
9
+ }
10
+
11
+ /**
12
+ * Accuracy level for location services.
13
+ * - 'high': GPS-level accuracy (~5-10 meters)
14
+ * - 'medium': Network-assisted accuracy (~100 meters)
15
+ * - 'low': Cell tower accuracy (~1000+ meters)
16
+ */
17
+ export type AccuracyLevel = "high" | "medium" | "low";
18
+
19
+ /**
20
+ * Merged configuration representing the optimal settings
21
+ * for multiple concurrent location requests.
22
+ */
23
+ export interface MergedConfiguration {
24
+ /** The best (highest) accuracy level among all requests */
25
+ bestAccuracy: AccuracyLevel;
26
+ /** The smallest (most sensitive) distance filter among all requests */
27
+ smallestDistanceFilter: number;
28
+ }
29
+
30
+ /**
31
+ * Merges multiple location request configurations to determine
32
+ * the optimal settings that satisfy all requests.
33
+ *
34
+ * This is important for battery optimization - when multiple watches
35
+ * or getCurrentPosition calls are active simultaneously, we should use
36
+ * the most demanding settings to satisfy all requests with a single
37
+ * location subscription.
38
+ *
39
+ * Strategy:
40
+ * - Use the highest accuracy level requested by any client
41
+ * - Use the smallest distance filter to ensure all clients get updates
42
+ *
43
+ * @param requests - Array of location requests to merge
44
+ * @returns Merged configuration with optimal settings
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * const requests = [
49
+ * { enableHighAccuracy: false, distanceFilter: 100 },
50
+ * { enableHighAccuracy: true, distanceFilter: 10 },
51
+ * { enableHighAccuracy: false, distanceFilter: 50 }
52
+ * ];
53
+ *
54
+ * const merged = mergeConfigurations(requests);
55
+ * // Result: { bestAccuracy: 'high', smallestDistanceFilter: 10 }
56
+ * ```
57
+ */
58
+ export function mergeConfigurations(
59
+ requests: LocationRequest[]
60
+ ): MergedConfiguration {
61
+ // If no requests, return default low-power settings
62
+ if (requests.length === 0) {
63
+ return {
64
+ bestAccuracy: "low",
65
+ smallestDistanceFilter: 0
66
+ };
67
+ }
68
+
69
+ let bestAccuracy: AccuracyLevel = "low";
70
+ let smallestDistanceFilter = Number.POSITIVE_INFINITY;
71
+
72
+ // Iterate through all requests to find the most demanding settings
73
+ for (const request of requests) {
74
+ // If any request needs high accuracy, use high accuracy
75
+ if (request.enableHighAccuracy) {
76
+ bestAccuracy = "high";
77
+ }
78
+
79
+ // Use the smallest distance filter
80
+ smallestDistanceFilter = Math.min(
81
+ smallestDistanceFilter,
82
+ request.distanceFilter
83
+ );
84
+ }
85
+
86
+ return {
87
+ bestAccuracy,
88
+ smallestDistanceFilter:
89
+ smallestDistanceFilter === Number.POSITIVE_INFINITY
90
+ ? 0
91
+ : smallestDistanceFilter
92
+ };
93
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Error codes for geolocation errors.
3
+ * These codes match the W3C Geolocation API specification.
4
+ */
5
+ export enum LocationErrorCode {
6
+ /** User denied the request for Geolocation */
7
+ PERMISSION_DENIED = 1,
8
+ /** Location provider is unavailable */
9
+ POSITION_UNAVAILABLE = 2,
10
+ /** The request to get location timed out */
11
+ TIMEOUT = 3
12
+ }
13
+
14
+ /**
15
+ * Geolocation error object.
16
+ */
17
+ export interface LocationError extends Error {
18
+ code: LocationErrorCode;
19
+ message: string;
20
+ PERMISSION_DENIED: LocationErrorCode.PERMISSION_DENIED;
21
+ POSITION_UNAVAILABLE: LocationErrorCode.POSITION_UNAVAILABLE;
22
+ TIMEOUT: LocationErrorCode.TIMEOUT;
23
+ }
24
+
25
+ /**
26
+ * Creates a standardized LocationError object.
27
+ *
28
+ * @param code - The error code from LocationErrorCode enum
29
+ * @param message - A human-readable error message
30
+ * @returns A LocationError object
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * const error = createLocationError(
35
+ * LocationErrorCode.PERMISSION_DENIED,
36
+ * 'User denied location permission'
37
+ * );
38
+ * ```
39
+ */
40
+ export function createLocationError(
41
+ code: LocationErrorCode,
42
+ message: string
43
+ ): LocationError {
44
+ const error = new Error(message) as LocationError;
45
+ error.code = code;
46
+ error.PERMISSION_DENIED = LocationErrorCode.PERMISSION_DENIED;
47
+ error.POSITION_UNAVAILABLE = LocationErrorCode.POSITION_UNAVAILABLE;
48
+ error.TIMEOUT = LocationErrorCode.TIMEOUT;
49
+ return error;
50
+ }
51
+
52
+ /**
53
+ * Maps iOS CLError codes to LocationErrorCode.
54
+ *
55
+ * @param clErrorCode - The iOS CLError code
56
+ * @returns The corresponding LocationErrorCode
57
+ *
58
+ * @see https://developer.apple.com/documentation/corelocation/clerror/code
59
+ */
60
+ export function mapCLErrorCode(clErrorCode: number): LocationErrorCode {
61
+ switch (clErrorCode) {
62
+ case 0: // kCLErrorDenied
63
+ return LocationErrorCode.PERMISSION_DENIED;
64
+ case 1: // kCLErrorLocationUnknown
65
+ return LocationErrorCode.POSITION_UNAVAILABLE;
66
+ default:
67
+ return LocationErrorCode.POSITION_UNAVAILABLE;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Maps Android exception types to LocationErrorCode.
73
+ *
74
+ * @param exceptionType - The Android exception class name
75
+ * @returns The corresponding LocationErrorCode
76
+ */
77
+ export function mapAndroidException(exceptionType: string): LocationErrorCode {
78
+ if (exceptionType === "SecurityException") {
79
+ return LocationErrorCode.PERMISSION_DENIED;
80
+ }
81
+ return LocationErrorCode.POSITION_UNAVAILABLE;
82
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Pure utility functions for geolocation operations.
3
+ * These functions are platform-independent and can be tested with Jest.
4
+ */
5
+
6
+ export { isCachedLocationValid } from "./cache";
7
+ export {
8
+ LocationErrorCode,
9
+ createLocationError,
10
+ mapCLErrorCode,
11
+ mapAndroidException,
12
+ type LocationError
13
+ } from "./errors";
14
+ export {
15
+ isBetterLocation,
16
+ type LocationQuality
17
+ } from "./quality";
18
+ export {
19
+ selectProvider,
20
+ type Provider
21
+ } from "./provider";
22
+ export {
23
+ mergeConfigurations,
24
+ type LocationRequest,
25
+ type AccuracyLevel,
26
+ type MergedConfiguration
27
+ } from "./config";
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Location provider types supported on Android.
3
+ */
4
+ export type Provider = "gps" | "network" | null;
5
+
6
+ /**
7
+ * Selects the best available location provider based on user preferences
8
+ * and provider availability.
9
+ *
10
+ * This function implements a fallback strategy:
11
+ * - If high accuracy is requested, prefer GPS, fallback to Network
12
+ * - If low power is preferred, prefer Network, fallback to GPS
13
+ *
14
+ * @param enableHighAccuracy - Whether high accuracy mode is requested
15
+ * @param gpsAvailable - Whether GPS provider is available and enabled
16
+ * @param networkAvailable - Whether Network provider is available and enabled
17
+ * @returns The selected provider, or null if no providers are available
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // High accuracy mode with both providers available
22
+ * selectProvider(true, true, true); // 'gps'
23
+ *
24
+ * // High accuracy mode but GPS is disabled
25
+ * selectProvider(true, false, true); // 'network'
26
+ *
27
+ * // Low power mode with both providers available
28
+ * selectProvider(false, true, true); // 'network'
29
+ *
30
+ * // No providers available
31
+ * selectProvider(true, false, false); // null
32
+ * ```
33
+ */
34
+ export function selectProvider(
35
+ enableHighAccuracy: boolean,
36
+ gpsAvailable: boolean,
37
+ networkAvailable: boolean
38
+ ): Provider {
39
+ // Determine preferred and fallback providers based on accuracy requirement
40
+ const preferredProvider = enableHighAccuracy ? "gps" : "network";
41
+ const fallbackProvider = enableHighAccuracy ? "network" : "gps";
42
+
43
+ // Check if preferred provider is available
44
+ const isPreferredAvailable =
45
+ preferredProvider === "gps" ? gpsAvailable : networkAvailable;
46
+
47
+ // Check if fallback provider is available
48
+ const isFallbackAvailable =
49
+ fallbackProvider === "gps" ? gpsAvailable : networkAvailable;
50
+
51
+ // Return the best available provider
52
+ if (isPreferredAvailable) {
53
+ return preferredProvider;
54
+ }
55
+
56
+ if (isFallbackAvailable) {
57
+ return fallbackProvider;
58
+ }
59
+
60
+ return null;
61
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Represents the quality characteristics of a location reading.
3
+ */
4
+ export interface LocationQuality {
5
+ /** Timestamp in milliseconds since epoch */
6
+ timestampMs: number;
7
+ /** Horizontal accuracy in meters */
8
+ accuracyMeters: number;
9
+ /** Location provider type */
10
+ provider: "gps" | "network";
11
+ }
12
+
13
+ /** Time threshold for considering locations significantly newer/older (2 minutes) */
14
+ const TWO_MINUTES_MS = 2 * 60 * 1000;
15
+
16
+ /** Accuracy threshold for considering locations significantly less accurate (200 meters) */
17
+ const SIGNIFICANT_ACCURACY_DIFFERENCE_METERS = 200;
18
+
19
+ /**
20
+ * Determines whether a new location is better than the current best location.
21
+ * This algorithm considers both recency and accuracy of location readings.
22
+ *
23
+ * Based on Android's location quality evaluation best practices:
24
+ * @see https://developer.android.com/develop/sensors-and-location/location/strategies#BestEstimate
25
+ *
26
+ * @param newLocation - The new location to evaluate
27
+ * @param currentBest - The current best location, or null if none exists
28
+ * @returns true if the new location is better, false otherwise
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const newLoc: LocationQuality = {
33
+ * timestampMs: Date.now(),
34
+ * accuracyMeters: 10,
35
+ * provider: 'gps'
36
+ * };
37
+ *
38
+ * const currentBest: LocationQuality = {
39
+ * timestampMs: Date.now() - 60000, // 1 minute ago
40
+ * accuracyMeters: 50,
41
+ * provider: 'network'
42
+ * };
43
+ *
44
+ * isBetterLocation(newLoc, currentBest); // true (newer and more accurate)
45
+ * ```
46
+ */
47
+ export function isBetterLocation(
48
+ newLocation: LocationQuality,
49
+ currentBest: LocationQuality | null
50
+ ): boolean {
51
+ // If there's no current best location, the new location is always better
52
+ if (!currentBest) {
53
+ return true;
54
+ }
55
+
56
+ // Calculate time difference between locations
57
+ const timeDelta = newLocation.timestampMs - currentBest.timestampMs;
58
+ const isSignificantlyNewer = timeDelta > TWO_MINUTES_MS;
59
+ const isSignificantlyOlder = timeDelta < -TWO_MINUTES_MS;
60
+
61
+ // If the new location is significantly newer, it's better
62
+ if (isSignificantlyNewer) {
63
+ return true;
64
+ }
65
+
66
+ // If the new location is significantly older, it's not better
67
+ if (isSignificantlyOlder) {
68
+ return false;
69
+ }
70
+
71
+ // Calculate accuracy difference
72
+ const accuracyDelta = newLocation.accuracyMeters - currentBest.accuracyMeters;
73
+ const isMoreAccurate = accuracyDelta < 0;
74
+ const isLessAccurate = accuracyDelta > 0;
75
+ const isSignificantlyLessAccurate =
76
+ accuracyDelta > SIGNIFICANT_ACCURACY_DIFFERENCE_METERS;
77
+
78
+ // Determine if location is newer
79
+ const isNewer = timeDelta > 0;
80
+
81
+ // Check if from same provider
82
+ const isFromSameProvider = newLocation.provider === currentBest.provider;
83
+
84
+ // Evaluate location quality based on accuracy and recency
85
+ if (isMoreAccurate) {
86
+ return true;
87
+ }
88
+
89
+ if (isNewer && !isLessAccurate) {
90
+ return true;
91
+ }
92
+
93
+ if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
94
+ return true;
95
+ }
96
+
97
+ return false;
98
+ }
package/src/clearWatch.ts DELETED
@@ -1,13 +0,0 @@
1
- import { NitroModules } from "react-native-nitro-modules";
2
- import type { NitroGeolocation } from "./NitroGeolocation.nitro";
3
-
4
- /**
5
- * Clears a specific watch session identified by watchId.
6
- *
7
- * @param watchId - The ID returned by watchPosition()
8
- */
9
- export function clearWatch(watchId: number): void {
10
- const nitroGeolocation =
11
- NitroModules.createHybridObject<NitroGeolocation>("NitroGeolocation");
12
- nitroGeolocation.clearWatch(watchId);
13
- }
@@ -1,9 +0,0 @@
1
- import { NitroGeolocationHybridObject } from "./NitroGeolocationModule";
2
- import type { GeolocationError } from "./types";
3
-
4
- export function requestAuthorization(
5
- success?: () => void,
6
- error?: (error: GeolocationError) => void
7
- ): void {
8
- NitroGeolocationHybridObject.requestAuthorization(success, error);
9
- }