react-native-nitro-geolocation 0.0.1 → 0.1.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.
- package/LICENSE +4 -1
- package/README.md +598 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/GetCurrentPosition.kt +341 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocation.kt +76 -5
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/RequestAuthorization.kt +164 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/WatchPosition.kt +228 -0
- package/ios/LocationManager.swift +529 -0
- package/ios/NitroGeolocation.swift +96 -2
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/c++/JAuthorizationLevelInternal.hpp +62 -0
- package/nitrogen/generated/android/c++/JFunc_void.hpp +74 -0
- package/nitrogen/generated/android/c++/JFunc_void_GeolocationError.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_GeolocationResponse.hpp +79 -0
- package/nitrogen/generated/android/c++/JGeolocationCoordinates.hpp +77 -0
- package/nitrogen/generated/android/c++/JGeolocationError.hpp +69 -0
- package/nitrogen/generated/android/c++/JGeolocationOptions.hpp +77 -0
- package/nitrogen/generated/android/c++/JGeolocationResponse.hpp +59 -0
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.cpp +98 -0
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.hpp +69 -0
- package/nitrogen/generated/android/c++/JLocationProviderInternal.hpp +62 -0
- package/nitrogen/generated/android/c++/JRNConfigurationInternal.hpp +69 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AuthorizationLevelInternal.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_GeolocationError.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_GeolocationResponse.kt +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationCoordinates.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationError.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationOptions.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationResponse.kt +32 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationSpec.kt +87 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderInternal.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/RNConfigurationInternal.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/nitrogeolocationOnLoad.kt +35 -0
- package/nitrogen/generated/android/nitrogeolocation+autolinking.cmake +81 -0
- package/nitrogen/generated/android/nitrogeolocation+autolinking.gradle +27 -0
- package/nitrogen/generated/android/nitrogeolocationOnLoad.cpp +50 -0
- package/nitrogen/generated/android/nitrogeolocationOnLoad.hpp +25 -0
- package/nitrogen/generated/ios/NitroGeolocation+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.cpp +56 -0
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.hpp +252 -0
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Umbrella.hpp +67 -0
- package/nitrogen/generated/ios/NitroGeolocationAutolinking.mm +33 -0
- package/nitrogen/generated/ios/NitroGeolocationAutolinking.swift +25 -0
- package/nitrogen/generated/ios/c++/HybridNitroGeolocationSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNitroGeolocationSpecSwift.hpp +125 -0
- package/nitrogen/generated/ios/swift/AuthorizationLevelInternal.swift +44 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_GeolocationError.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_GeolocationResponse.swift +47 -0
- package/nitrogen/generated/ios/swift/GeolocationCoordinates.swift +149 -0
- package/nitrogen/generated/ios/swift/GeolocationError.swift +79 -0
- package/nitrogen/generated/ios/swift/GeolocationOptions.swift +185 -0
- package/nitrogen/generated/ios/swift/GeolocationResponse.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec.swift +54 -0
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec_cxx.swift +236 -0
- package/nitrogen/generated/ios/swift/LocationProviderInternal.swift +44 -0
- package/nitrogen/generated/ios/swift/RNConfigurationInternal.swift +104 -0
- package/nitrogen/generated/shared/c++/AuthorizationLevelInternal.hpp +80 -0
- package/nitrogen/generated/shared/c++/GeolocationCoordinates.hpp +91 -0
- package/nitrogen/generated/shared/c++/GeolocationError.hpp +83 -0
- package/nitrogen/generated/shared/c++/GeolocationOptions.hpp +91 -0
- package/nitrogen/generated/shared/c++/GeolocationResponse.hpp +72 -0
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.hpp +79 -0
- package/nitrogen/generated/shared/c++/LocationProviderInternal.hpp +80 -0
- package/nitrogen/generated/shared/c++/RNConfigurationInternal.hpp +84 -0
- package/package.json +34 -10
- package/src/NitroGeolocation.nitro.ts +38 -3
- package/src/NitroGeolocationModule.ts +5 -0
- package/src/clearWatch.ts +13 -0
- package/src/getCurrentPosition.ts +14 -0
- package/src/index.tsx +32 -7
- package/src/requestAuthorization.ts +9 -0
- package/src/setRNConfiguration.ts +22 -0
- package/src/stopObserving.ts +12 -0
- package/src/types.ts +43 -0
- package/src/watchPosition.ts +26 -0
- package/nitro.json +0 -17
- package/turbo.json +0 -42
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrogeolocation
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.pm.PackageManager
|
|
6
|
+
import android.location.Location
|
|
7
|
+
import android.location.LocationListener
|
|
8
|
+
import android.location.LocationManager
|
|
9
|
+
import android.os.Bundle
|
|
10
|
+
import android.os.Looper
|
|
11
|
+
import android.util.Log
|
|
12
|
+
import androidx.core.content.ContextCompat
|
|
13
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
14
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
15
|
+
import java.util.concurrent.atomic.AtomicInteger
|
|
16
|
+
|
|
17
|
+
class WatchPosition(private val reactContext: ReactApplicationContext) {
|
|
18
|
+
|
|
19
|
+
private val watchCallbacks = ConcurrentHashMap<Int, WatchCallback>()
|
|
20
|
+
private val watchIdGenerator = AtomicInteger(0)
|
|
21
|
+
private var locationListener: LocationListener? = null
|
|
22
|
+
private var watchedProvider: String? = null
|
|
23
|
+
private var currentOptions: GeolocationOptions? = null
|
|
24
|
+
|
|
25
|
+
data class WatchCallback(
|
|
26
|
+
val success: (GeolocationResponse) -> Unit,
|
|
27
|
+
val error: ((GeolocationError) -> Unit)?,
|
|
28
|
+
val options: GeolocationOptions?
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
fun watch(
|
|
32
|
+
success: (GeolocationResponse) -> Unit,
|
|
33
|
+
error: ((GeolocationError) -> Unit)?,
|
|
34
|
+
options: GeolocationOptions?
|
|
35
|
+
): Int {
|
|
36
|
+
val watchId = watchIdGenerator.incrementAndGet()
|
|
37
|
+
watchCallbacks[watchId] = WatchCallback(success, error, options)
|
|
38
|
+
|
|
39
|
+
// Start observing if this is the first watch
|
|
40
|
+
if (watchCallbacks.size == 1) {
|
|
41
|
+
startObserving(options)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return watchId
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
fun clearWatch(watchId: Int) {
|
|
48
|
+
watchCallbacks.remove(watchId)
|
|
49
|
+
|
|
50
|
+
// Stop observing if no more watches
|
|
51
|
+
if (watchCallbacks.isEmpty()) {
|
|
52
|
+
stopObserving()
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
fun stopObserving() {
|
|
57
|
+
val locationManager =
|
|
58
|
+
reactContext.getSystemService(Context.LOCATION_SERVICE) as? LocationManager
|
|
59
|
+
|
|
60
|
+
locationListener?.let { listener -> locationManager?.removeUpdates(listener) }
|
|
61
|
+
|
|
62
|
+
locationListener = null
|
|
63
|
+
watchedProvider = null
|
|
64
|
+
currentOptions = null
|
|
65
|
+
watchCallbacks.clear()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private fun startObserving(options: GeolocationOptions?) {
|
|
69
|
+
val locationManager =
|
|
70
|
+
reactContext.getSystemService(Context.LOCATION_SERVICE) as? LocationManager
|
|
71
|
+
|
|
72
|
+
if (locationManager == null) {
|
|
73
|
+
Log.e(TAG, "LocationManager is not available")
|
|
74
|
+
emitErrorToAll(
|
|
75
|
+
createError(
|
|
76
|
+
GetCurrentPosition.POSITION_UNAVAILABLE,
|
|
77
|
+
"LocationManager is not available"
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
val opts = parseOptions(options)
|
|
84
|
+
val provider = getValidProvider(locationManager, opts.enableHighAccuracy)
|
|
85
|
+
|
|
86
|
+
if (provider == null) {
|
|
87
|
+
Log.e(TAG, "No location provider available")
|
|
88
|
+
emitErrorToAll(
|
|
89
|
+
createError(
|
|
90
|
+
GetCurrentPosition.POSITION_UNAVAILABLE,
|
|
91
|
+
"No location provider available"
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// If already watching with the same provider, don't restart
|
|
98
|
+
if (provider == watchedProvider) {
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
// Remove old listener if exists
|
|
104
|
+
locationListener?.let { locationManager.removeUpdates(it) }
|
|
105
|
+
|
|
106
|
+
// Create new listener
|
|
107
|
+
val listener =
|
|
108
|
+
object : LocationListener {
|
|
109
|
+
override fun onLocationChanged(location: Location) {
|
|
110
|
+
val position = locationToPosition(location)
|
|
111
|
+
// Call all watch callbacks
|
|
112
|
+
watchCallbacks.values.forEach { callback -> callback.success(position) }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
override fun onStatusChanged(
|
|
116
|
+
provider: String?,
|
|
117
|
+
status: Int,
|
|
118
|
+
extras: Bundle?
|
|
119
|
+
) {}
|
|
120
|
+
override fun onProviderEnabled(provider: String) {}
|
|
121
|
+
override fun onProviderDisabled(provider: String) {}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
locationManager.requestLocationUpdates(
|
|
125
|
+
provider,
|
|
126
|
+
opts.interval.toLong(),
|
|
127
|
+
opts.distanceFilter.toFloat(),
|
|
128
|
+
listener,
|
|
129
|
+
Looper.getMainLooper()
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
locationListener = listener
|
|
133
|
+
watchedProvider = provider
|
|
134
|
+
currentOptions = options
|
|
135
|
+
} catch (e: SecurityException) {
|
|
136
|
+
Log.e(TAG, "SecurityException: ${e.message}")
|
|
137
|
+
emitErrorToAll(
|
|
138
|
+
createError(
|
|
139
|
+
GetCurrentPosition.PERMISSION_DENIED,
|
|
140
|
+
"Location permission denied: ${e.message}"
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private fun emitErrorToAll(error: GeolocationError) {
|
|
147
|
+
watchCallbacks.values.forEach { callback -> callback.error?.invoke(error) }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private fun parseOptions(options: GeolocationOptions?): ParsedOptions {
|
|
151
|
+
return ParsedOptions(
|
|
152
|
+
interval = options?.interval ?: DEFAULT_INTERVAL,
|
|
153
|
+
distanceFilter = options?.distanceFilter ?: DEFAULT_DISTANCE_FILTER,
|
|
154
|
+
enableHighAccuracy = options?.enableHighAccuracy ?: false
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private fun getValidProvider(locationManager: LocationManager, highAccuracy: Boolean): String? {
|
|
159
|
+
val preferredProvider =
|
|
160
|
+
if (highAccuracy) LocationManager.GPS_PROVIDER else LocationManager.NETWORK_PROVIDER
|
|
161
|
+
val fallbackProvider =
|
|
162
|
+
if (highAccuracy) LocationManager.NETWORK_PROVIDER else LocationManager.GPS_PROVIDER
|
|
163
|
+
|
|
164
|
+
return when {
|
|
165
|
+
isProviderValid(locationManager, preferredProvider) -> preferredProvider
|
|
166
|
+
isProviderValid(locationManager, fallbackProvider) -> fallbackProvider
|
|
167
|
+
else -> null
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private fun isProviderValid(locationManager: LocationManager, provider: String): Boolean {
|
|
172
|
+
if (!locationManager.isProviderEnabled(provider)) return false
|
|
173
|
+
|
|
174
|
+
val permission =
|
|
175
|
+
if (provider == LocationManager.GPS_PROVIDER)
|
|
176
|
+
Manifest.permission.ACCESS_FINE_LOCATION
|
|
177
|
+
else Manifest.permission.ACCESS_COARSE_LOCATION
|
|
178
|
+
|
|
179
|
+
return ContextCompat.checkSelfPermission(reactContext, permission) ==
|
|
180
|
+
PackageManager.PERMISSION_GRANTED
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private fun locationToPosition(location: Location): GeolocationResponse {
|
|
184
|
+
return GeolocationResponse(
|
|
185
|
+
coords =
|
|
186
|
+
GeolocationCoordinates(
|
|
187
|
+
latitude = location.latitude,
|
|
188
|
+
longitude = location.longitude,
|
|
189
|
+
altitude = if (location.hasAltitude()) location.altitude else null,
|
|
190
|
+
accuracy = location.accuracy.toDouble(),
|
|
191
|
+
altitudeAccuracy =
|
|
192
|
+
if (android.os.Build.VERSION.SDK_INT >=
|
|
193
|
+
android.os.Build.VERSION_CODES.O &&
|
|
194
|
+
location.hasVerticalAccuracy()
|
|
195
|
+
)
|
|
196
|
+
location.verticalAccuracyMeters.toDouble()
|
|
197
|
+
else null,
|
|
198
|
+
heading =
|
|
199
|
+
if (location.hasBearing()) location.bearing.toDouble()
|
|
200
|
+
else null,
|
|
201
|
+
speed = if (location.hasSpeed()) location.speed.toDouble() else null
|
|
202
|
+
),
|
|
203
|
+
timestamp = location.time.toDouble()
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private fun createError(code: Int, message: String): GeolocationError {
|
|
208
|
+
return GeolocationError(
|
|
209
|
+
code = code.toDouble(),
|
|
210
|
+
message = message,
|
|
211
|
+
PERMISSION_DENIED = GetCurrentPosition.PERMISSION_DENIED.toDouble(),
|
|
212
|
+
POSITION_UNAVAILABLE = GetCurrentPosition.POSITION_UNAVAILABLE.toDouble(),
|
|
213
|
+
TIMEOUT = GetCurrentPosition.TIMEOUT.toDouble()
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private data class ParsedOptions(
|
|
218
|
+
val interval: Double,
|
|
219
|
+
val distanceFilter: Double,
|
|
220
|
+
val enableHighAccuracy: Boolean
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
companion object {
|
|
224
|
+
private const val TAG = "WatchPosition"
|
|
225
|
+
const val DEFAULT_INTERVAL = 1000.0 // 1 second
|
|
226
|
+
const val DEFAULT_DISTANCE_FILTER = 100.0 // 100 meters
|
|
227
|
+
}
|
|
228
|
+
}
|