react-native-nitro-geolocation 1.1.4 → 1.2.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.
- package/README.md +97 -9
- package/android/build.gradle +6 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidAccuracy.kt +105 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidHeadingManager.kt +313 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidLocationSettings.kt +313 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/GetCurrentPosition.kt +46 -45
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/LocationMetadata.kt +26 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/LocationValues.kt +31 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocation.kt +1027 -140
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocationCompat.kt +11 -11
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/RequestAuthorization.kt +6 -6
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/WatchPosition.kt +46 -45
- package/ios/CLLocation+GeolocationMetadata.swift +32 -0
- package/ios/LocationManager.swift +205 -51
- package/ios/NitroGeolocation.swift +949 -110
- package/ios/NitroGeolocationCompat.swift +7 -7
- package/nitrogen/generated/android/c++/JAccuracyAuthorization.hpp +61 -0
- package/nitrogen/generated/android/c++/JAndroidAccuracyPreset.hpp +64 -0
- package/nitrogen/generated/android/c++/JAndroidGranularity.hpp +61 -0
- package/nitrogen/generated/android/c++/{JRNConfigurationInternal.hpp → JCompatGeolocationConfigurationInternal.hpp} +10 -10
- package/nitrogen/generated/android/c++/{JGeolocationError.hpp → JCompatGeolocationError.hpp} +10 -10
- package/nitrogen/generated/android/c++/JCompatGeolocationOptions.hpp +105 -0
- package/nitrogen/generated/android/c++/JCompatGeolocationResponse.hpp +67 -0
- package/nitrogen/generated/android/c++/JFunc_void_AccuracyAuthorization.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_CompatGeolocationError.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_CompatGeolocationResponse.hpp +84 -0
- package/nitrogen/generated/android/c++/JFunc_void_GeolocationResponse.hpp +2 -0
- package/nitrogen/generated/android/c++/JFunc_void_Heading.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_LocationProviderStatus.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_PermissionStatus.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_GeocodedLocation_.hpp +97 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__vector_ReverseGeocodedAddress_.hpp +98 -0
- package/nitrogen/generated/android/c++/JGeocodedLocation.hpp +65 -0
- package/nitrogen/generated/android/c++/JGeocodingCoordinates.hpp +61 -0
- package/nitrogen/generated/android/c++/{JModernGeolocationConfiguration.hpp → JGeolocationConfiguration.hpp} +10 -10
- package/nitrogen/generated/android/c++/JGeolocationResponse.hpp +13 -3
- package/nitrogen/generated/android/c++/JHeading.hpp +69 -0
- package/nitrogen/generated/android/c++/JHeadingOptions.hpp +57 -0
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationCompatSpec.cpp +46 -30
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationCompatSpec.hpp +4 -4
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.cpp +169 -33
- package/nitrogen/generated/android/c++/JHybridNitroGeolocationSpec.hpp +14 -3
- package/nitrogen/generated/android/c++/JIOSAccuracyPreset.hpp +73 -0
- package/nitrogen/generated/android/c++/JIOSActivityType.hpp +67 -0
- package/nitrogen/generated/android/c++/JLocationAccuracyOptions.hpp +65 -0
- package/nitrogen/generated/android/c++/JLocationAvailability.hpp +62 -0
- package/nitrogen/generated/android/c++/JLocationProviderStatus.hpp +77 -0
- package/nitrogen/generated/android/c++/JLocationProviderUsed.hpp +67 -0
- package/nitrogen/generated/android/c++/JLocationRequestOptions.hpp +49 -3
- package/nitrogen/generated/android/c++/{JGeolocationOptions.hpp → JLocationSettingsOptions.hpp} +28 -22
- package/nitrogen/generated/android/c++/JReverseGeocodedAddress.hpp +82 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AccuracyAuthorization.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidAccuracyPreset.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidGranularity.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/{RNConfigurationInternal.kt → CompatGeolocationConfigurationInternal.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/{GeolocationError.kt → CompatGeolocationError.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/CompatGeolocationOptions.kt +68 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/CompatGeolocationResponse.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_AccuracyAuthorization.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/{Func_void_GeolocationError.kt → Func_void_CompatGeolocationError.kt} +9 -9
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_CompatGeolocationResponse.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_Heading.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_LocationProviderStatus.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_PermissionStatus.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_std__vector_GeocodedLocation_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_std__vector_ReverseGeocodedAddress_.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeocodedLocation.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeocodingCoordinates.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/{ModernGeolocationConfiguration.kt → GeolocationConfiguration.kt} +5 -5
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeolocationResponse.kt +9 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Heading.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HeadingOptions.kt +38 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationCompatSpec.kt +7 -7
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroGeolocationSpec.kt +92 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSAccuracyPreset.kt +28 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSActivityType.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationAccuracyOptions.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationAvailability.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderStatus.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderUsed.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationRequestOptions.kt +30 -3
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/{GeolocationOptions.kt → LocationSettingsOptions.kt} +11 -11
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/ReverseGeocodedAddress.kt +56 -0
- package/nitrogen/generated/android/nitrogeolocationOnLoad.cpp +18 -4
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.cpp +76 -12
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.hpp +519 -77
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Umbrella.hpp +61 -12
- package/nitrogen/generated/ios/c++/HybridNitroGeolocationCompatSpecSwift.hpp +28 -16
- package/nitrogen/generated/ios/c++/HybridNitroGeolocationSpecSwift.hpp +131 -13
- package/nitrogen/generated/ios/swift/AccuracyAuthorization.swift +44 -0
- package/nitrogen/generated/ios/swift/AndroidAccuracyPreset.swift +48 -0
- package/nitrogen/generated/ios/swift/AndroidGranularity.swift +44 -0
- package/nitrogen/generated/ios/swift/{RNConfigurationInternal.swift → CompatGeolocationConfigurationInternal.swift} +5 -5
- package/nitrogen/generated/ios/swift/{GeolocationError.swift → CompatGeolocationError.swift} +5 -5
- package/nitrogen/generated/ios/swift/CompatGeolocationOptions.swift +208 -0
- package/nitrogen/generated/ios/swift/CompatGeolocationResponse.swift +34 -0
- package/nitrogen/generated/ios/swift/Func_void_AccuracyAuthorization.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CompatGeolocationError.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_CompatGeolocationResponse.swift +46 -0
- package/nitrogen/generated/ios/swift/{Func_void_GeolocationError.swift → Func_void_Heading.swift} +11 -11
- package/nitrogen/generated/ios/swift/Func_void_LocationAvailability.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_LocationProviderStatus.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_GeocodedLocation_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_ReverseGeocodedAddress_.swift +46 -0
- package/nitrogen/generated/ios/swift/GeocodedLocation.swift +52 -0
- package/nitrogen/generated/ios/swift/GeocodingCoordinates.swift +34 -0
- package/nitrogen/generated/ios/swift/{ModernGeolocationConfiguration.swift → GeolocationConfiguration.swift} +5 -5
- package/nitrogen/generated/ios/swift/GeolocationResponse.swift +31 -2
- package/nitrogen/generated/ios/swift/Heading.swift +70 -0
- package/nitrogen/generated/ios/swift/HeadingOptions.swift +42 -0
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationCompatSpec.swift +4 -4
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationCompatSpec_cxx.swift +28 -28
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec.swift +14 -3
- package/nitrogen/generated/ios/swift/HybridNitroGeolocationSpec_cxx.swift +318 -15
- package/nitrogen/generated/ios/swift/IOSAccuracyPreset.swift +60 -0
- package/nitrogen/generated/ios/swift/IOSActivityType.swift +52 -0
- package/nitrogen/generated/ios/swift/LocationAccuracyOptions.swift +46 -0
- package/nitrogen/generated/ios/swift/LocationAvailability.swift +47 -0
- package/nitrogen/generated/ios/swift/LocationProviderStatus.swift +106 -0
- package/nitrogen/generated/ios/swift/LocationProviderUsed.swift +52 -0
- package/nitrogen/generated/ios/swift/LocationRequestOptions.swift +142 -1
- package/nitrogen/generated/ios/swift/{GeolocationOptions.swift → LocationSettingsOptions.swift} +39 -46
- package/nitrogen/generated/ios/swift/ReverseGeocodedAddress.swift +150 -0
- package/nitrogen/generated/shared/c++/AccuracyAuthorization.hpp +80 -0
- package/nitrogen/generated/shared/c++/AndroidAccuracyPreset.hpp +84 -0
- package/nitrogen/generated/shared/c++/AndroidGranularity.hpp +80 -0
- package/nitrogen/generated/shared/c++/{RNConfigurationInternal.hpp → CompatGeolocationConfigurationInternal.hpp} +11 -11
- package/nitrogen/generated/shared/c++/{GeolocationError.hpp → CompatGeolocationError.hpp} +11 -11
- package/nitrogen/generated/shared/c++/CompatGeolocationOptions.hpp +128 -0
- package/nitrogen/generated/shared/c++/CompatGeolocationResponse.hpp +88 -0
- package/nitrogen/generated/shared/c++/GeocodedLocation.hpp +91 -0
- package/nitrogen/generated/shared/c++/GeocodingCoordinates.hpp +87 -0
- package/nitrogen/generated/shared/c++/{ModernGeolocationConfiguration.hpp → GeolocationConfiguration.hpp} +11 -11
- package/nitrogen/generated/shared/c++/GeolocationResponse.hpp +14 -2
- package/nitrogen/generated/shared/c++/Heading.hpp +95 -0
- package/nitrogen/generated/shared/c++/HeadingOptions.hpp +83 -0
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationCompatSpec.hpp +16 -16
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.cpp +11 -0
- package/nitrogen/generated/shared/c++/HybridNitroGeolocationSpec.hpp +51 -12
- package/nitrogen/generated/shared/c++/IOSAccuracyPreset.hpp +96 -0
- package/nitrogen/generated/shared/c++/IOSActivityType.hpp +88 -0
- package/nitrogen/generated/shared/c++/LocationAccuracyOptions.hpp +92 -0
- package/nitrogen/generated/shared/c++/LocationAvailability.hpp +88 -0
- package/nitrogen/generated/shared/c++/LocationProviderStatus.hpp +103 -0
- package/nitrogen/generated/shared/c++/LocationProviderUsed.hpp +88 -0
- package/nitrogen/generated/shared/c++/LocationRequestOptions.hpp +47 -3
- package/nitrogen/generated/shared/c++/{GeolocationOptions.hpp → LocationSettingsOptions.hpp} +26 -24
- package/nitrogen/generated/shared/c++/ReverseGeocodedAddress.hpp +108 -0
- package/package.json +1 -1
- package/src/NitroGeolocation.nitro.ts +292 -18
- package/src/NitroGeolocationCompat.nitro.ts +12 -12
- package/src/api/geocode.ts +18 -0
- package/src/api/getAccuracyAuthorization.ts +12 -0
- package/src/api/getCurrentPosition.ts +5 -3
- package/src/api/getHeading.ts +13 -0
- package/src/api/getLastKnownPosition.ts +28 -0
- package/src/api/getLocationAvailability.ts +11 -0
- package/src/api/getProviderStatus.ts +16 -0
- package/src/api/hasServicesEnabled.ts +13 -0
- package/src/api/index.ts +11 -0
- package/src/api/requestLocationSettings.ts +29 -0
- package/src/api/requestPermission.ts +3 -1
- package/src/api/requestTemporaryFullAccuracy.ts +21 -0
- package/src/api/reverseGeocode.ts +23 -0
- package/src/api/setConfiguration.ts +8 -4
- package/src/api/watchHeading.ts +19 -0
- package/src/api/watchPosition.ts +2 -2
- package/src/compat/getCurrentPosition.ts +7 -7
- package/src/compat/index.tsx +5 -5
- package/src/compat/requestAuthorization.ts +2 -2
- package/src/compat/setRNConfiguration.ts +7 -5
- package/src/compat/watchPosition.ts +7 -7
- package/src/devtools/getCurrentPosition.ts +5 -3
- package/src/devtools/index.ts +1 -1
- package/src/devtools/watchPosition.ts +6 -7
- package/src/hooks/useWatchPosition.ts +2 -2
- package/src/index.tsx +35 -6
- package/src/publicTypes.ts +108 -0
- package/src/types.ts +113 -37
- package/src/utils/errors.test.ts +65 -0
- package/src/utils/errors.ts +45 -18
- package/src/utils/index.ts +2 -2
- package/src/utils/provider.test.ts +172 -1
- package/src/utils/provider.ts +50 -5
- package/nitrogen/generated/android/c++/JFunc_void_GeolocationError.hpp +0 -78
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrogeolocation
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.app.Activity
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.content.Intent
|
|
7
|
+
import android.content.IntentSender
|
|
8
|
+
import android.content.pm.PackageManager
|
|
9
|
+
import android.location.LocationManager as AndroidLocationManager
|
|
10
|
+
import android.os.Build
|
|
11
|
+
import android.os.Handler
|
|
12
|
+
import android.os.Looper
|
|
13
|
+
import androidx.core.content.ContextCompat
|
|
14
|
+
import com.facebook.react.bridge.BaseActivityEventListener
|
|
15
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
16
|
+
import com.google.android.gms.common.ConnectionResult
|
|
17
|
+
import com.google.android.gms.common.GoogleApiAvailability
|
|
18
|
+
import com.google.android.gms.common.api.ResolvableApiException
|
|
19
|
+
import com.google.android.gms.location.LocationRequest as GmsLocationRequest
|
|
20
|
+
import com.google.android.gms.location.LocationServices
|
|
21
|
+
import com.google.android.gms.location.LocationSettingsRequest
|
|
22
|
+
import com.google.android.gms.location.Priority
|
|
23
|
+
import java.util.concurrent.atomic.AtomicBoolean
|
|
24
|
+
|
|
25
|
+
private const val LOCATION_SETTINGS_REQUEST_CODE = 8948
|
|
26
|
+
private const val GOOGLE_LOCATION_ACCURACY_TIMEOUT_MS = 2_000L
|
|
27
|
+
|
|
28
|
+
internal class AndroidLocationSettings(
|
|
29
|
+
private val reactContext: ReactApplicationContext,
|
|
30
|
+
private val locationManager: AndroidLocationManager,
|
|
31
|
+
private val createLocationError: (Double, String) -> LocationError,
|
|
32
|
+
private val createPlayServicesUnavailableError: () -> LocationError
|
|
33
|
+
) {
|
|
34
|
+
private data class ParsedSettingsOptions(
|
|
35
|
+
val androidAccuracy: AndroidAccuracyResolution,
|
|
36
|
+
val intervalMillis: Long,
|
|
37
|
+
val fastestIntervalMillis: Long,
|
|
38
|
+
val distanceFilterMeters: Float,
|
|
39
|
+
val alwaysShow: Boolean,
|
|
40
|
+
val needBle: Boolean
|
|
41
|
+
) {
|
|
42
|
+
companion object {
|
|
43
|
+
private const val DEFAULT_INTERVAL_MS = 5_000.0
|
|
44
|
+
private const val DEFAULT_FASTEST_INTERVAL_MS = 1_000.0
|
|
45
|
+
private const val DEFAULT_DISTANCE_FILTER_METERS = 0.0
|
|
46
|
+
|
|
47
|
+
fun parse(options: LocationSettingsOptions?): ParsedSettingsOptions {
|
|
48
|
+
val enableHighAccuracy = options?.enableHighAccuracy ?: true
|
|
49
|
+
return ParsedSettingsOptions(
|
|
50
|
+
androidAccuracy = resolveAndroidAccuracy(
|
|
51
|
+
options?.accuracy,
|
|
52
|
+
enableHighAccuracy
|
|
53
|
+
),
|
|
54
|
+
intervalMillis = coercePositiveMillis(
|
|
55
|
+
options?.interval,
|
|
56
|
+
DEFAULT_INTERVAL_MS
|
|
57
|
+
),
|
|
58
|
+
fastestIntervalMillis = coercePositiveMillis(
|
|
59
|
+
options?.fastestInterval,
|
|
60
|
+
DEFAULT_FASTEST_INTERVAL_MS
|
|
61
|
+
),
|
|
62
|
+
distanceFilterMeters = (options?.distanceFilter
|
|
63
|
+
?: DEFAULT_DISTANCE_FILTER_METERS)
|
|
64
|
+
.coerceAtLeast(0.0)
|
|
65
|
+
.toFloat(),
|
|
66
|
+
alwaysShow = options?.alwaysShow ?: true,
|
|
67
|
+
needBle = options?.needBle ?: false
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private fun coercePositiveMillis(value: Double?, defaultValue: Double): Long {
|
|
72
|
+
val nextValue = value ?: defaultValue
|
|
73
|
+
return when {
|
|
74
|
+
nextValue.isNaN() || nextValue <= 0.0 -> defaultValue.toLong()
|
|
75
|
+
nextValue.isInfinite() || nextValue >= Long.MAX_VALUE.toDouble() -> Long.MAX_VALUE
|
|
76
|
+
else -> nextValue.toLong()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private data class PendingLocationSettingsRequest(
|
|
83
|
+
val success: (LocationProviderStatus) -> Unit,
|
|
84
|
+
val error: ((LocationError) -> Unit)?,
|
|
85
|
+
val options: ParsedSettingsOptions
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
private var pendingLocationSettingsRequest: PendingLocationSettingsRequest? = null
|
|
89
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
90
|
+
|
|
91
|
+
private val activityEventListener = object : BaseActivityEventListener() {
|
|
92
|
+
override fun onActivityResult(
|
|
93
|
+
activity: Activity,
|
|
94
|
+
requestCode: Int,
|
|
95
|
+
resultCode: Int,
|
|
96
|
+
data: Intent?
|
|
97
|
+
) {
|
|
98
|
+
if (requestCode != LOCATION_SETTINGS_REQUEST_CODE) return
|
|
99
|
+
|
|
100
|
+
val pendingRequest = pendingLocationSettingsRequest ?: return
|
|
101
|
+
pendingLocationSettingsRequest = null
|
|
102
|
+
|
|
103
|
+
if (resultCode == Activity.RESULT_OK) {
|
|
104
|
+
checkLocationSettings(pendingRequest, shouldShowResolution = false)
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
pendingRequest.error?.invoke(createLocationError(
|
|
109
|
+
SETTINGS_NOT_SATISFIED,
|
|
110
|
+
"Location settings change was cancelled."
|
|
111
|
+
))
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
init {
|
|
116
|
+
reactContext.addActivityEventListener(activityEventListener)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
fun hasServicesEnabled(): Boolean {
|
|
120
|
+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
121
|
+
locationManager.isLocationEnabled
|
|
122
|
+
} else {
|
|
123
|
+
isProviderEnabled(AndroidLocationManager.GPS_PROVIDER) ||
|
|
124
|
+
isProviderEnabled(AndroidLocationManager.NETWORK_PROVIDER)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fun getProviderStatus(success: (LocationProviderStatus) -> Unit) {
|
|
129
|
+
getGoogleLocationAccuracyEnabled { googleLocationAccuracyEnabled ->
|
|
130
|
+
success(createProviderStatus(googleLocationAccuracyEnabled))
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
private fun createProviderStatus(
|
|
135
|
+
googleLocationAccuracyEnabled: Boolean?
|
|
136
|
+
): LocationProviderStatus {
|
|
137
|
+
return LocationProviderStatus(
|
|
138
|
+
locationServicesEnabled = hasServicesEnabled(),
|
|
139
|
+
backgroundModeEnabled = hasBackgroundLocationPermission(),
|
|
140
|
+
gpsAvailable = isProviderEnabled(AndroidLocationManager.GPS_PROVIDER),
|
|
141
|
+
networkAvailable = isProviderEnabled(AndroidLocationManager.NETWORK_PROVIDER),
|
|
142
|
+
passiveAvailable = isProviderEnabled(AndroidLocationManager.PASSIVE_PROVIDER),
|
|
143
|
+
googleLocationAccuracyEnabled = googleLocationAccuracyEnabled
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
fun requestLocationSettings(
|
|
148
|
+
success: (LocationProviderStatus) -> Unit,
|
|
149
|
+
error: ((LocationError) -> Unit)?,
|
|
150
|
+
options: LocationSettingsOptions?
|
|
151
|
+
) {
|
|
152
|
+
if (!isGooglePlayServicesAvailable()) {
|
|
153
|
+
error?.invoke(createPlayServicesUnavailableError())
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (pendingLocationSettingsRequest != null) {
|
|
158
|
+
error?.invoke(createLocationError(
|
|
159
|
+
INTERNAL_ERROR,
|
|
160
|
+
"A location settings request is already in progress."
|
|
161
|
+
))
|
|
162
|
+
return
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
val pendingRequest = PendingLocationSettingsRequest(
|
|
166
|
+
success = success,
|
|
167
|
+
error = error,
|
|
168
|
+
options = ParsedSettingsOptions.parse(options)
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
checkLocationSettings(pendingRequest, shouldShowResolution = true)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private fun checkLocationSettings(
|
|
175
|
+
pendingRequest: PendingLocationSettingsRequest,
|
|
176
|
+
shouldShowResolution: Boolean
|
|
177
|
+
) {
|
|
178
|
+
val settingsClient = LocationServices.getSettingsClient(reactContext)
|
|
179
|
+
settingsClient
|
|
180
|
+
.checkLocationSettings(buildLocationSettingsRequest(pendingRequest.options))
|
|
181
|
+
.addOnSuccessListener {
|
|
182
|
+
getProviderStatus(pendingRequest.success)
|
|
183
|
+
}
|
|
184
|
+
.addOnFailureListener { exception ->
|
|
185
|
+
if (shouldShowResolution && exception is ResolvableApiException) {
|
|
186
|
+
showResolutionDialog(exception, pendingRequest)
|
|
187
|
+
return@addOnFailureListener
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
pendingRequest.error?.invoke(createLocationError(
|
|
191
|
+
SETTINGS_NOT_SATISFIED,
|
|
192
|
+
"Location settings do not satisfy the requested options."
|
|
193
|
+
))
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private fun showResolutionDialog(
|
|
198
|
+
exception: ResolvableApiException,
|
|
199
|
+
pendingRequest: PendingLocationSettingsRequest
|
|
200
|
+
) {
|
|
201
|
+
val activity = reactContext.currentActivity
|
|
202
|
+
if (activity == null) {
|
|
203
|
+
pendingRequest.error?.invoke(createLocationError(
|
|
204
|
+
INTERNAL_ERROR,
|
|
205
|
+
"No activity available to request location settings."
|
|
206
|
+
))
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
pendingLocationSettingsRequest = pendingRequest
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
exception.startResolutionForResult(activity, LOCATION_SETTINGS_REQUEST_CODE)
|
|
214
|
+
} catch (e: IntentSender.SendIntentException) {
|
|
215
|
+
pendingLocationSettingsRequest = null
|
|
216
|
+
pendingRequest.error?.invoke(createLocationError(
|
|
217
|
+
INTERNAL_ERROR,
|
|
218
|
+
"Failed to show location settings dialog: ${e.message}"
|
|
219
|
+
))
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private fun buildLocationSettingsRequest(
|
|
224
|
+
options: ParsedSettingsOptions
|
|
225
|
+
): LocationSettingsRequest {
|
|
226
|
+
val priority = when (options.androidAccuracy.mode) {
|
|
227
|
+
AndroidAccuracyMode.HIGH -> Priority.PRIORITY_HIGH_ACCURACY
|
|
228
|
+
AndroidAccuracyMode.BALANCED -> Priority.PRIORITY_BALANCED_POWER_ACCURACY
|
|
229
|
+
AndroidAccuracyMode.LOW -> Priority.PRIORITY_LOW_POWER
|
|
230
|
+
AndroidAccuracyMode.PASSIVE -> Priority.PRIORITY_PASSIVE
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
val request = GmsLocationRequest
|
|
234
|
+
.Builder(priority, options.intervalMillis)
|
|
235
|
+
.setMinUpdateIntervalMillis(options.fastestIntervalMillis)
|
|
236
|
+
.setMinUpdateDistanceMeters(options.distanceFilterMeters)
|
|
237
|
+
.build()
|
|
238
|
+
|
|
239
|
+
return LocationSettingsRequest
|
|
240
|
+
.Builder()
|
|
241
|
+
.addLocationRequest(request)
|
|
242
|
+
.setAlwaysShow(options.alwaysShow)
|
|
243
|
+
.setNeedBle(options.needBle)
|
|
244
|
+
.build()
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private fun isProviderEnabled(provider: String): Boolean {
|
|
248
|
+
return try {
|
|
249
|
+
locationManager.isProviderEnabled(provider)
|
|
250
|
+
} catch (e: Exception) {
|
|
251
|
+
false
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
private fun hasBackgroundLocationPermission(): Boolean {
|
|
256
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return true
|
|
257
|
+
|
|
258
|
+
return ContextCompat.checkSelfPermission(
|
|
259
|
+
reactContext,
|
|
260
|
+
Manifest.permission.ACCESS_BACKGROUND_LOCATION
|
|
261
|
+
) == PackageManager.PERMISSION_GRANTED
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private fun getGoogleLocationAccuracyEnabled(success: (Boolean?) -> Unit) {
|
|
265
|
+
if (!isGooglePlayServicesAvailable()) {
|
|
266
|
+
success(null)
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
val didComplete = AtomicBoolean(false)
|
|
271
|
+
val timeoutRunnable = Runnable {
|
|
272
|
+
if (didComplete.compareAndSet(false, true)) {
|
|
273
|
+
success(null)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
fun complete(value: Boolean?) {
|
|
278
|
+
if (didComplete.compareAndSet(false, true)) {
|
|
279
|
+
mainHandler.removeCallbacks(timeoutRunnable)
|
|
280
|
+
success(value)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
mainHandler.postDelayed(timeoutRunnable, GOOGLE_LOCATION_ACCURACY_TIMEOUT_MS)
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
LocationServices
|
|
288
|
+
.getSettingsClient(reactContext)
|
|
289
|
+
.isGoogleLocationAccuracyEnabled
|
|
290
|
+
.addOnSuccessListener { enabled ->
|
|
291
|
+
complete(enabled)
|
|
292
|
+
}
|
|
293
|
+
.addOnFailureListener {
|
|
294
|
+
complete(null)
|
|
295
|
+
}
|
|
296
|
+
.addOnCanceledListener {
|
|
297
|
+
complete(null)
|
|
298
|
+
}
|
|
299
|
+
} catch (e: Exception) {
|
|
300
|
+
complete(null)
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
private fun isGooglePlayServicesAvailable(): Boolean {
|
|
305
|
+
return GoogleApiAvailability.getInstance()
|
|
306
|
+
.isGooglePlayServicesAvailable(reactContext) == ConnectionResult.SUCCESS
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private companion object {
|
|
310
|
+
private const val INTERNAL_ERROR = -1.0
|
|
311
|
+
private const val SETTINGS_NOT_SATISFIED = 5.0
|
|
312
|
+
}
|
|
313
|
+
}
|
|
@@ -16,9 +16,9 @@ import com.facebook.react.bridge.ReactApplicationContext
|
|
|
16
16
|
class GetCurrentPosition(private val reactContext: ReactApplicationContext) {
|
|
17
17
|
|
|
18
18
|
fun execute(
|
|
19
|
-
success: (position:
|
|
20
|
-
error: ((error:
|
|
21
|
-
options:
|
|
19
|
+
success: (position: CompatGeolocationResponse) -> Unit,
|
|
20
|
+
error: ((error: CompatGeolocationError) -> Unit)?,
|
|
21
|
+
options: CompatGeolocationOptions?
|
|
22
22
|
) {
|
|
23
23
|
val locationManager =
|
|
24
24
|
reactContext.getSystemService(Context.LOCATION_SERVICE) as? LocationManager
|
|
@@ -29,7 +29,7 @@ class GetCurrentPosition(private val reactContext: ReactApplicationContext) {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
val opts = parseOptions(options)
|
|
32
|
-
val provider = getValidProvider(locationManager, opts.
|
|
32
|
+
val provider = getValidProvider(locationManager, opts.androidAccuracy)
|
|
33
33
|
|
|
34
34
|
if (provider == null) {
|
|
35
35
|
Log.e(TAG, "No location provider available")
|
|
@@ -64,11 +64,15 @@ class GetCurrentPosition(private val reactContext: ReactApplicationContext) {
|
|
|
64
64
|
|
|
65
65
|
// ===== Helper Functions =====
|
|
66
66
|
|
|
67
|
-
private fun parseOptions(options:
|
|
67
|
+
private fun parseOptions(options: CompatGeolocationOptions?): ParsedOptions {
|
|
68
68
|
return ParsedOptions(
|
|
69
69
|
timeout = options?.timeout ?: DEFAULT_TIMEOUT,
|
|
70
70
|
maximumAge = options?.maximumAge ?: DEFAULT_MAXIMUM_AGE,
|
|
71
|
-
|
|
71
|
+
androidAccuracy =
|
|
72
|
+
resolveAndroidAccuracy(
|
|
73
|
+
options?.accuracy,
|
|
74
|
+
options?.enableHighAccuracy ?: false
|
|
75
|
+
)
|
|
72
76
|
)
|
|
73
77
|
}
|
|
74
78
|
|
|
@@ -77,37 +81,42 @@ class GetCurrentPosition(private val reactContext: ReactApplicationContext) {
|
|
|
77
81
|
return age < options.maximumAge
|
|
78
82
|
}
|
|
79
83
|
|
|
80
|
-
private fun getValidProvider(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return when {
|
|
87
|
-
isProviderValid(locationManager, preferredProvider) -> preferredProvider
|
|
88
|
-
isProviderValid(locationManager, fallbackProvider) -> fallbackProvider
|
|
89
|
-
else -> null
|
|
84
|
+
private fun getValidProvider(
|
|
85
|
+
locationManager: LocationManager,
|
|
86
|
+
accuracy: AndroidAccuracyResolution
|
|
87
|
+
): String? {
|
|
88
|
+
return accuracy.providerOrder().firstOrNull { provider ->
|
|
89
|
+
isProviderValid(locationManager, provider)
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
private fun isProviderValid(locationManager: LocationManager, provider: String): Boolean {
|
|
94
94
|
if (!locationManager.isProviderEnabled(provider)) return false
|
|
95
95
|
|
|
96
|
-
val
|
|
97
|
-
|
|
96
|
+
val fineGranted =
|
|
97
|
+
ContextCompat.checkSelfPermission(
|
|
98
|
+
reactContext,
|
|
98
99
|
Manifest.permission.ACCESS_FINE_LOCATION
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
) == PackageManager.PERMISSION_GRANTED
|
|
101
|
+
val coarseGranted =
|
|
102
|
+
ContextCompat.checkSelfPermission(
|
|
103
|
+
reactContext,
|
|
104
|
+
Manifest.permission.ACCESS_COARSE_LOCATION
|
|
105
|
+
) == PackageManager.PERMISSION_GRANTED
|
|
106
|
+
|
|
107
|
+
return if (provider == LocationManager.GPS_PROVIDER) {
|
|
108
|
+
fineGranted
|
|
109
|
+
} else {
|
|
110
|
+
coarseGranted || fineGranted
|
|
111
|
+
}
|
|
103
112
|
}
|
|
104
113
|
|
|
105
114
|
private fun requestFreshLocation(
|
|
106
115
|
locationManager: LocationManager,
|
|
107
116
|
provider: String,
|
|
108
117
|
options: ParsedOptions,
|
|
109
|
-
success: (
|
|
110
|
-
error: ((
|
|
118
|
+
success: (CompatGeolocationResponse) -> Unit,
|
|
119
|
+
error: ((CompatGeolocationError) -> Unit)?,
|
|
111
120
|
fallbackLocation: Location?
|
|
112
121
|
) {
|
|
113
122
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
|
@@ -138,8 +147,8 @@ class GetCurrentPosition(private val reactContext: ReactApplicationContext) {
|
|
|
138
147
|
locationManager: LocationManager,
|
|
139
148
|
provider: String,
|
|
140
149
|
options: ParsedOptions,
|
|
141
|
-
success: (
|
|
142
|
-
error: ((
|
|
150
|
+
success: (CompatGeolocationResponse) -> Unit,
|
|
151
|
+
error: ((CompatGeolocationError) -> Unit)?,
|
|
143
152
|
fallbackLocation: Location?
|
|
144
153
|
) {
|
|
145
154
|
val handler = Handler(Looper.getMainLooper())
|
|
@@ -187,8 +196,8 @@ class GetCurrentPosition(private val reactContext: ReactApplicationContext) {
|
|
|
187
196
|
locationManager: LocationManager,
|
|
188
197
|
provider: String,
|
|
189
198
|
options: ParsedOptions,
|
|
190
|
-
success: (
|
|
191
|
-
error: ((
|
|
199
|
+
success: (CompatGeolocationResponse) -> Unit,
|
|
200
|
+
error: ((CompatGeolocationError) -> Unit)?,
|
|
192
201
|
fallbackLocation: Location?
|
|
193
202
|
) {
|
|
194
203
|
val handler = Handler(Looper.getMainLooper())
|
|
@@ -285,32 +294,24 @@ class GetCurrentPosition(private val reactContext: ReactApplicationContext) {
|
|
|
285
294
|
|
|
286
295
|
// ===== Data Conversion =====
|
|
287
296
|
|
|
288
|
-
private fun locationToPosition(location: Location):
|
|
289
|
-
return
|
|
297
|
+
private fun locationToPosition(location: Location): CompatGeolocationResponse {
|
|
298
|
+
return CompatGeolocationResponse(
|
|
290
299
|
coords =
|
|
291
300
|
GeolocationCoordinates(
|
|
292
301
|
latitude = location.latitude,
|
|
293
302
|
longitude = location.longitude,
|
|
294
|
-
altitude =
|
|
303
|
+
altitude = location.altitudeValue(),
|
|
295
304
|
accuracy = location.accuracy.toDouble(),
|
|
296
|
-
altitudeAccuracy =
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
location.hasVerticalAccuracy()
|
|
300
|
-
)
|
|
301
|
-
NullableDouble.create(location.verticalAccuracyMeters.toDouble())
|
|
302
|
-
else null,
|
|
303
|
-
heading =
|
|
304
|
-
if (location.hasBearing()) NullableDouble.create(location.bearing.toDouble())
|
|
305
|
-
else null,
|
|
306
|
-
speed = if (location.hasSpeed()) NullableDouble.create(location.speed.toDouble()) else null
|
|
305
|
+
altitudeAccuracy = location.altitudeAccuracyValue(),
|
|
306
|
+
heading = location.headingValue(),
|
|
307
|
+
speed = location.speedValue()
|
|
307
308
|
),
|
|
308
309
|
timestamp = location.time.toDouble()
|
|
309
310
|
)
|
|
310
311
|
}
|
|
311
312
|
|
|
312
|
-
private fun createError(code: Int, message: String):
|
|
313
|
-
return
|
|
313
|
+
private fun createError(code: Int, message: String): CompatGeolocationError {
|
|
314
|
+
return CompatGeolocationError(
|
|
314
315
|
code = code.toDouble(),
|
|
315
316
|
message = message,
|
|
316
317
|
PERMISSION_DENIED = PERMISSION_DENIED.toDouble(),
|
|
@@ -324,7 +325,7 @@ class GetCurrentPosition(private val reactContext: ReactApplicationContext) {
|
|
|
324
325
|
private data class ParsedOptions(
|
|
325
326
|
val timeout: Double,
|
|
326
327
|
val maximumAge: Double,
|
|
327
|
-
val
|
|
328
|
+
val androidAccuracy: AndroidAccuracyResolution
|
|
328
329
|
)
|
|
329
330
|
|
|
330
331
|
companion object {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrogeolocation
|
|
2
|
+
|
|
3
|
+
import android.location.Location
|
|
4
|
+
import android.location.LocationManager
|
|
5
|
+
import android.os.Build
|
|
6
|
+
|
|
7
|
+
private const val FUSED_PROVIDER = "fused"
|
|
8
|
+
|
|
9
|
+
internal fun Location.isMocked(): Boolean {
|
|
10
|
+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
11
|
+
isMock
|
|
12
|
+
} else {
|
|
13
|
+
@Suppress("DEPRECATION")
|
|
14
|
+
isFromMockProvider
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
internal fun Location.providerUsed(): LocationProviderUsed {
|
|
19
|
+
return when (provider) {
|
|
20
|
+
FUSED_PROVIDER -> LocationProviderUsed.FUSED
|
|
21
|
+
LocationManager.GPS_PROVIDER -> LocationProviderUsed.GPS
|
|
22
|
+
LocationManager.NETWORK_PROVIDER -> LocationProviderUsed.NETWORK
|
|
23
|
+
LocationManager.PASSIVE_PROVIDER -> LocationProviderUsed.PASSIVE
|
|
24
|
+
else -> LocationProviderUsed.UNKNOWN
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package com.margelo.nitro.nitrogeolocation
|
|
2
|
+
|
|
3
|
+
import android.location.Location
|
|
4
|
+
import android.os.Build
|
|
5
|
+
import com.margelo.nitro.core.NullType.Companion.NULL
|
|
6
|
+
|
|
7
|
+
internal fun nullableDouble(value: Double?): NullableDouble {
|
|
8
|
+
return value?.let { NullableDouble.create(it) } ?: NullableDouble.create(NULL)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
internal fun Location.altitudeValue(): NullableDouble {
|
|
12
|
+
return nullableDouble(if (hasAltitude()) altitude else null)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
internal fun Location.altitudeAccuracyValue(): NullableDouble {
|
|
16
|
+
return nullableDouble(
|
|
17
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasVerticalAccuracy()) {
|
|
18
|
+
verticalAccuracyMeters.toDouble()
|
|
19
|
+
} else {
|
|
20
|
+
null
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
internal fun Location.headingValue(): NullableDouble {
|
|
26
|
+
return nullableDouble(if (hasBearing()) bearing.toDouble() else null)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
internal fun Location.speedValue(): NullableDouble {
|
|
30
|
+
return nullableDouble(if (hasSpeed()) speed.toDouble() else null)
|
|
31
|
+
}
|