react-native-nitro-geolocation 1.2.6 → 1.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.
- package/README.md +52 -295
- package/android/build.gradle +1 -0
- package/android/src/main/AndroidManifest.xml +39 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidFusedLocationProvider.kt +310 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidFusedRequestFactory.kt +31 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationConversions.kt +71 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationErrors.kt +85 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationOptions.kt +92 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidLocationSettings.kt +3 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidProviderRoute.kt +74 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroBackgroundLocation.kt +132 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocation.kt +219 -476
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundHttpSync.kt +134 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundPermissions.kt +196 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundSerialization.kt +266 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroActivityRecognitionReceiver.kt +13 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundEventHub.kt +65 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundHeadlessTaskService.kt +58 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundLocationController.kt +710 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundLocationService.kt +48 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundNotificationFactory.kt +37 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundStore.kt +655 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBootReceiver.kt +26 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroGeofenceReceiver.kt +14 -0
- package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroLocationUpdateReceiver.kt +37 -0
- package/android/src/test/java/com/margelo/nitro/nitrogeolocation/AndroidFusedLocationProviderTest.kt +64 -0
- package/android/src/test/java/com/margelo/nitro/nitrogeolocation/AndroidProviderRouteTest.kt +116 -0
- package/ios/IOSBackgroundHttpSync.swift +126 -0
- package/ios/IOSBackgroundLocationDelegate.swift +36 -0
- package/ios/IOSBackgroundMotion.swift +55 -0
- package/ios/IOSBackgroundSerialization.swift +539 -0
- package/ios/IOSGeolocationConversions.swift +131 -0
- package/ios/IOSGeolocationDelegate.swift +31 -0
- package/ios/IOSGeolocationErrors.swift +39 -0
- package/ios/IOSGeolocationOptions.swift +135 -0
- package/ios/NitroBackgroundLocation.swift +849 -0
- package/ios/NitroGeolocation.swift +14 -347
- package/nitrogen/generated/android/c++/JActivityRecognitionOptions.hpp +69 -0
- package/nitrogen/generated/android/c++/JAndroidBackgroundLocationOptions.hpp +74 -0
- package/nitrogen/generated/android/c++/JAndroidBackgroundLocationStatus.hpp +67 -0
- package/nitrogen/generated/android/c++/JAndroidBackgroundProvider.hpp +61 -0
- package/nitrogen/generated/android/c++/JAndroidForegroundServiceOptions.hpp +90 -0
- package/nitrogen/generated/android/c++/JBackgroundEventEnvelope.hpp +129 -0
- package/nitrogen/generated/android/c++/JBackgroundEventType.hpp +70 -0
- package/nitrogen/generated/android/c++/JBackgroundHttpMethod.hpp +61 -0
- package/nitrogen/generated/android/c++/JBackgroundHttpSyncOptions.hpp +131 -0
- package/nitrogen/generated/android/c++/JBackgroundHttpSyncResult.hpp +111 -0
- package/nitrogen/generated/android/c++/JBackgroundLocation.hpp +110 -0
- package/nitrogen/generated/android/c++/JBackgroundLocationOptions.hpp +162 -0
- package/nitrogen/generated/android/c++/JBackgroundLocationSource.hpp +73 -0
- package/nitrogen/generated/android/c++/JBackgroundLocationState.hpp +70 -0
- package/nitrogen/generated/android/c++/JBackgroundLocationStatus.hpp +126 -0
- package/nitrogen/generated/android/c++/JBackgroundPermissionResult.hpp +79 -0
- package/nitrogen/generated/android/c++/JBackgroundPermissionStatus.hpp +64 -0
- package/nitrogen/generated/android/c++/JBackgroundTrackingMode.hpp +61 -0
- package/nitrogen/generated/android/c++/JBatterySnapshot.hpp +61 -0
- package/nitrogen/generated/android/c++/JDetectedActivity.hpp +66 -0
- package/nitrogen/generated/android/c++/JDetectedActivityType.hpp +76 -0
- package/nitrogen/generated/android/c++/JFunc_void_BackgroundEventEnvelope.hpp +114 -0
- package/nitrogen/generated/android/c++/JFunc_void_BackgroundLocation.hpp +95 -0
- package/nitrogen/generated/android/c++/JGeofenceEvent.hpp +94 -0
- package/nitrogen/generated/android/c++/JGeofenceRegion.hpp +112 -0
- package/nitrogen/generated/android/c++/JGeofenceTransition.hpp +61 -0
- package/nitrogen/generated/android/c++/JGeofencingOptions.hpp +82 -0
- package/nitrogen/generated/android/c++/JGetStoredBackgroundEventsOptions.hpp +90 -0
- package/nitrogen/generated/android/c++/JGetStoredBackgroundLocationsOptions.hpp +69 -0
- package/nitrogen/generated/android/c++/JHybridNitroBackgroundLocationSpec.cpp +662 -0
- package/nitrogen/generated/android/c++/JHybridNitroBackgroundLocationSpec.hpp +89 -0
- package/nitrogen/generated/android/c++/JIOSBackgroundActivityType.hpp +67 -0
- package/nitrogen/generated/android/c++/JIOSBackgroundLocationOptions.hpp +79 -0
- package/nitrogen/generated/android/c++/JIOSBackgroundLocationStatus.hpp +61 -0
- package/nitrogen/generated/android/c++/JLocationProviderStatus.hpp +5 -1
- package/nitrogen/generated/android/c++/JStoredBackgroundEventEnvelope.hpp +115 -0
- package/nitrogen/generated/android/c++/JStoredBackgroundLocation.hpp +122 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Boolean_String_Double.cpp +34 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_Boolean_String_Double.hpp +100 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/ActivityRecognitionOptions.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundLocationOptions.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundLocationStatus.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundProvider.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidForegroundServiceOptions.kt +91 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundEventEnvelope.kt +96 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundEventType.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpMethod.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpSyncOptions.kt +101 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpSyncResult.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocation.kt +96 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationOptions.kt +136 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationSource.kt +28 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationState.kt +27 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationStatus.kt +116 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundPermissionResult.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundPermissionStatus.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundTrackingMode.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BatterySnapshot.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/DetectedActivity.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/DetectedActivityType.kt +29 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_BackgroundEventEnvelope.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_BackgroundLocation.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceEvent.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceRegion.kt +96 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceTransition.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofencingOptions.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GetStoredBackgroundEventsOptions.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GetStoredBackgroundLocationsOptions.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroBackgroundLocationSpec.kt +174 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundActivityType.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundLocationOptions.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundLocationStatus.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderStatus.kt +7 -2
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/StoredBackgroundEventEnvelope.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/StoredBackgroundLocation.kt +111 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Variant_NullType_Boolean_String_Double.kt +88 -0
- package/nitrogen/generated/android/nitrogeolocation+autolinking.cmake +3 -0
- package/nitrogen/generated/android/nitrogeolocationOnLoad.cpp +20 -0
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.cpp +104 -15
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.hpp +1107 -50
- package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Umbrella.hpp +102 -0
- package/nitrogen/generated/ios/NitroGeolocationAutolinking.mm +8 -0
- package/nitrogen/generated/ios/NitroGeolocationAutolinking.swift +15 -3
- package/nitrogen/generated/ios/c++/HybridNitroBackgroundLocationSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNitroBackgroundLocationSpecSwift.hpp +416 -0
- package/nitrogen/generated/ios/swift/ActivityRecognitionOptions.swift +96 -0
- package/nitrogen/generated/ios/swift/AndroidBackgroundLocationOptions.swift +76 -0
- package/nitrogen/generated/ios/swift/AndroidBackgroundLocationStatus.swift +58 -0
- package/nitrogen/generated/ios/swift/AndroidBackgroundProvider.swift +44 -0
- package/nitrogen/generated/ios/swift/AndroidForegroundServiceOptions.swift +160 -0
- package/nitrogen/generated/ios/swift/BackgroundEventEnvelope.swift +110 -0
- package/nitrogen/generated/ios/swift/BackgroundEventType.swift +56 -0
- package/nitrogen/generated/ios/swift/BackgroundHttpMethod.swift +44 -0
- package/nitrogen/generated/ios/swift/BackgroundHttpSyncOptions.swift +259 -0
- package/nitrogen/generated/ios/swift/BackgroundHttpSyncResult.swift +87 -0
- package/nitrogen/generated/ios/swift/BackgroundLocation.swift +118 -0
- package/nitrogen/generated/ios/swift/BackgroundLocationOptions.swift +292 -0
- package/nitrogen/generated/ios/swift/BackgroundLocationSource.swift +60 -0
- package/nitrogen/generated/ios/swift/BackgroundLocationState.swift +56 -0
- package/nitrogen/generated/ios/swift/BackgroundLocationStatus.swift +124 -0
- package/nitrogen/generated/ios/swift/BackgroundPermissionResult.swift +81 -0
- package/nitrogen/generated/ios/swift/BackgroundPermissionStatus.swift +48 -0
- package/nitrogen/generated/ios/swift/BackgroundTrackingMode.swift +44 -0
- package/nitrogen/generated/ios/swift/BatterySnapshot.swift +60 -0
- package/nitrogen/generated/ios/swift/DetectedActivity.swift +39 -0
- package/nitrogen/generated/ios/swift/DetectedActivityType.swift +64 -0
- package/nitrogen/generated/ios/swift/Func_void_BackgroundEventEnvelope.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_BackgroundHttpSyncResult.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_BackgroundLocation.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_BackgroundLocationStatus.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_BackgroundPermissionResult.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__optional_BackgroundLocationOptions_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_GeofenceRegion_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_StoredBackgroundEventEnvelope_.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__vector_StoredBackgroundLocation_.swift +46 -0
- package/nitrogen/generated/ios/swift/GeofenceEvent.swift +50 -0
- package/nitrogen/generated/ios/swift/GeofenceRegion.swift +195 -0
- package/nitrogen/generated/ios/swift/GeofenceTransition.swift +44 -0
- package/nitrogen/generated/ios/swift/GeofencingOptions.swift +66 -0
- package/nitrogen/generated/ios/swift/GetStoredBackgroundEventsOptions.swift +102 -0
- package/nitrogen/generated/ios/swift/GetStoredBackgroundLocationsOptions.swift +96 -0
- package/nitrogen/generated/ios/swift/HybridNitroBackgroundLocationSpec.swift +81 -0
- package/nitrogen/generated/ios/swift/HybridNitroBackgroundLocationSpec_cxx.swift +654 -0
- package/nitrogen/generated/ios/swift/IOSBackgroundActivityType.swift +52 -0
- package/nitrogen/generated/ios/swift/IOSBackgroundLocationOptions.swift +125 -0
- package/nitrogen/generated/ios/swift/IOSBackgroundLocationStatus.swift +34 -0
- package/nitrogen/generated/ios/swift/LocationProviderStatus.swift +19 -1
- package/nitrogen/generated/ios/swift/StoredBackgroundEventEnvelope.swift +54 -0
- package/nitrogen/generated/ios/swift/StoredBackgroundLocation.swift +120 -0
- package/nitrogen/generated/ios/swift/Variant_NullType_Bool_String_Double.swift +34 -0
- package/nitrogen/generated/shared/c++/ActivityRecognitionOptions.hpp +95 -0
- package/nitrogen/generated/shared/c++/AndroidBackgroundLocationOptions.hpp +100 -0
- package/nitrogen/generated/shared/c++/AndroidBackgroundLocationStatus.hpp +93 -0
- package/nitrogen/generated/shared/c++/AndroidBackgroundProvider.hpp +80 -0
- package/nitrogen/generated/shared/c++/AndroidForegroundServiceOptions.hpp +116 -0
- package/nitrogen/generated/shared/c++/BackgroundEventEnvelope.hpp +140 -0
- package/nitrogen/generated/shared/c++/BackgroundEventType.hpp +92 -0
- package/nitrogen/generated/shared/c++/BackgroundHttpMethod.hpp +80 -0
- package/nitrogen/generated/shared/c++/BackgroundHttpSyncOptions.hpp +129 -0
- package/nitrogen/generated/shared/c++/BackgroundHttpSyncResult.hpp +101 -0
- package/nitrogen/generated/shared/c++/BackgroundLocation.hpp +134 -0
- package/nitrogen/generated/shared/c++/BackgroundLocationOptions.hpp +174 -0
- package/nitrogen/generated/shared/c++/BackgroundLocationSource.hpp +96 -0
- package/nitrogen/generated/shared/c++/BackgroundLocationState.hpp +92 -0
- package/nitrogen/generated/shared/c++/BackgroundLocationStatus.hpp +158 -0
- package/nitrogen/generated/shared/c++/BackgroundPermissionResult.hpp +107 -0
- package/nitrogen/generated/shared/c++/BackgroundPermissionStatus.hpp +84 -0
- package/nitrogen/generated/shared/c++/BackgroundTrackingMode.hpp +80 -0
- package/nitrogen/generated/shared/c++/BatterySnapshot.hpp +87 -0
- package/nitrogen/generated/shared/c++/DetectedActivity.hpp +92 -0
- package/nitrogen/generated/shared/c++/DetectedActivityType.hpp +100 -0
- package/nitrogen/generated/shared/c++/GeofenceEvent.hpp +103 -0
- package/nitrogen/generated/shared/c++/GeofenceRegion.hpp +123 -0
- package/nitrogen/generated/shared/c++/GeofenceTransition.hpp +80 -0
- package/nitrogen/generated/shared/c++/GeofencingOptions.hpp +90 -0
- package/nitrogen/generated/shared/c++/GetStoredBackgroundEventsOptions.hpp +98 -0
- package/nitrogen/generated/shared/c++/GetStoredBackgroundLocationsOptions.hpp +95 -0
- package/nitrogen/generated/shared/c++/HybridNitroBackgroundLocationSpec.cpp +47 -0
- package/nitrogen/generated/shared/c++/HybridNitroBackgroundLocationSpec.hpp +133 -0
- package/nitrogen/generated/shared/c++/IOSBackgroundActivityType.hpp +88 -0
- package/nitrogen/generated/shared/c++/IOSBackgroundLocationOptions.hpp +105 -0
- package/nitrogen/generated/shared/c++/IOSBackgroundLocationStatus.hpp +87 -0
- package/nitrogen/generated/shared/c++/LocationProviderStatus.hpp +5 -1
- package/nitrogen/generated/shared/c++/StoredBackgroundEventEnvelope.hpp +108 -0
- package/nitrogen/generated/shared/c++/StoredBackgroundLocation.hpp +146 -0
- package/package.json +17 -6
- package/src/NitroGeolocation.nitro.ts +4 -4
- package/src/api/getCurrentPosition.ts +1 -1
- package/src/api/requestLocationSettings.ts +3 -2
- package/src/background/NitroBackgroundLocation.nitro.ts +83 -0
- package/src/background/index.ts +200 -0
- package/src/background/index.web.ts +120 -0
- package/src/background/task.ts +13 -0
- package/src/background/types.ts +328 -0
- package/src/compat/index.web.ts +141 -0
- package/src/index.tsx +3 -0
- package/src/index.web.tsx +41 -0
- package/src/publicTypes.ts +6 -5
- package/src/types.ts +3 -0
- package/src/web/browser.ts +171 -0
- package/src/web/index.ts +167 -0
- package/src/web/useWatchPosition.ts +76 -0
- package/src/web/watch.ts +81 -0
- package/src/devtools/index.test.ts +0 -54
- package/src/utils/errors.test.ts +0 -65
- package/src/utils/provider.test.ts +0 -303
|
@@ -3,7 +3,6 @@ package com.margelo.nitro.nitrogeolocation
|
|
|
3
3
|
import android.Manifest
|
|
4
4
|
import android.content.Context
|
|
5
5
|
import android.content.pm.PackageManager
|
|
6
|
-
import android.location.Address
|
|
7
6
|
import android.location.Geocoder
|
|
8
7
|
import android.location.Location
|
|
9
8
|
import android.location.LocationListener
|
|
@@ -13,14 +12,14 @@ import android.os.CancellationSignal
|
|
|
13
12
|
import android.os.Handler
|
|
14
13
|
import android.os.Looper
|
|
15
14
|
import android.os.SystemClock
|
|
16
|
-
import androidx.core.app.ActivityCompat
|
|
17
15
|
import androidx.core.content.ContextCompat
|
|
18
16
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
19
17
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
18
|
+
import com.facebook.react.modules.core.PermissionAwareActivity
|
|
19
|
+
import com.facebook.react.modules.core.PermissionListener
|
|
20
20
|
import com.google.android.gms.common.ConnectionResult
|
|
21
21
|
import com.google.android.gms.common.GoogleApiAvailability
|
|
22
22
|
import com.google.android.gms.location.LocationCallback
|
|
23
|
-
import com.google.android.gms.location.LocationRequest as GmsLocationRequest
|
|
24
23
|
import com.google.android.gms.location.LocationResult
|
|
25
24
|
import com.google.android.gms.location.LocationServices
|
|
26
25
|
import com.margelo.nitro.NitroModules
|
|
@@ -29,12 +28,7 @@ import java.io.IOException
|
|
|
29
28
|
import java.util.Locale
|
|
30
29
|
import java.util.UUID
|
|
31
30
|
import java.util.concurrent.ConcurrentHashMap
|
|
32
|
-
import java.util.concurrent.atomic.
|
|
33
|
-
|
|
34
|
-
private const val NO_LOCATION_PROVIDER_AVAILABLE_MESSAGE = "No location provider available"
|
|
35
|
-
private const val NO_APPROXIMATE_LOCATION_PROVIDER_AVAILABLE_MESSAGE =
|
|
36
|
-
"No location provider is available for approximate location. " +
|
|
37
|
-
"ACCESS_COARSE_LOCATION is granted, but no enabled coarse-compatible provider is available."
|
|
31
|
+
import java.util.concurrent.atomic.AtomicLong
|
|
38
32
|
|
|
39
33
|
/**
|
|
40
34
|
* Geolocation implementation for Android.
|
|
@@ -50,94 +44,6 @@ class NitroGeolocation(
|
|
|
50
44
|
private val reactContext: ReactApplicationContext = NitroModules.applicationContext!!
|
|
51
45
|
) : HybridNitroGeolocationSpec() {
|
|
52
46
|
|
|
53
|
-
// MARK: - Types
|
|
54
|
-
|
|
55
|
-
private data class ParsedOptions(
|
|
56
|
-
val timeout: Double,
|
|
57
|
-
val maximumAge: Double,
|
|
58
|
-
val androidAccuracy: AndroidAccuracyResolution,
|
|
59
|
-
val interval: Double,
|
|
60
|
-
val fastestInterval: Double,
|
|
61
|
-
val distanceFilter: Double,
|
|
62
|
-
val granularity: AndroidGranularity,
|
|
63
|
-
val waitForAccurateLocation: Boolean,
|
|
64
|
-
val maxUpdateAge: Double?,
|
|
65
|
-
val maxUpdateDelay: Double,
|
|
66
|
-
val maxUpdates: Int?
|
|
67
|
-
) {
|
|
68
|
-
companion object {
|
|
69
|
-
private const val DEFAULT_TIMEOUT = 10.0 * 60 * 1000 // 10 minutes in ms
|
|
70
|
-
private const val DEFAULT_MAXIMUM_AGE = 0.0
|
|
71
|
-
private const val DEFAULT_INTERVAL = 1000.0
|
|
72
|
-
private const val DEFAULT_FASTEST_INTERVAL = 100.0
|
|
73
|
-
private const val DEFAULT_DISTANCE_FILTER = 0.0
|
|
74
|
-
private const val DEFAULT_MAX_UPDATE_DELAY = 0.0
|
|
75
|
-
|
|
76
|
-
fun parse(
|
|
77
|
-
options: LocationRequestOptions?,
|
|
78
|
-
defaultMaximumAge: Double = DEFAULT_MAXIMUM_AGE
|
|
79
|
-
): ParsedOptions {
|
|
80
|
-
val enableHighAccuracy = options?.enableHighAccuracy ?: false
|
|
81
|
-
val maxUpdates = options?.maxUpdates?.let { value ->
|
|
82
|
-
if (!value.isFinite()) {
|
|
83
|
-
0
|
|
84
|
-
} else {
|
|
85
|
-
value.toInt()
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return ParsedOptions(
|
|
90
|
-
timeout = options?.timeout ?: DEFAULT_TIMEOUT,
|
|
91
|
-
maximumAge = options?.maximumAge ?: defaultMaximumAge,
|
|
92
|
-
androidAccuracy = resolveAndroidAccuracy(
|
|
93
|
-
options?.accuracy,
|
|
94
|
-
enableHighAccuracy
|
|
95
|
-
),
|
|
96
|
-
interval = options?.interval ?: DEFAULT_INTERVAL,
|
|
97
|
-
fastestInterval = options?.fastestInterval ?: DEFAULT_FASTEST_INTERVAL,
|
|
98
|
-
distanceFilter = options?.distanceFilter ?: DEFAULT_DISTANCE_FILTER,
|
|
99
|
-
granularity = options?.granularity ?: AndroidGranularity.PERMISSION,
|
|
100
|
-
waitForAccurateLocation = options?.waitForAccurateLocation ?: false,
|
|
101
|
-
maxUpdateAge = options?.maxUpdateAge,
|
|
102
|
-
maxUpdateDelay = options?.maxUpdateDelay ?: DEFAULT_MAX_UPDATE_DELAY,
|
|
103
|
-
maxUpdates = maxUpdates
|
|
104
|
-
)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
fun parseLastKnown(options: LocationRequestOptions?): ParsedOptions {
|
|
108
|
-
return parse(options, defaultMaximumAge = Double.POSITIVE_INFINITY)
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
private data class WatchSubscription(
|
|
114
|
-
val token: String,
|
|
115
|
-
val success: (GeolocationResponse) -> Unit,
|
|
116
|
-
val error: ((LocationError) -> Unit)?,
|
|
117
|
-
val options: ParsedOptions,
|
|
118
|
-
var deliveredUpdates: Int = 0
|
|
119
|
-
)
|
|
120
|
-
|
|
121
|
-
private sealed interface PositionResult {
|
|
122
|
-
data class Success(val position: GeolocationResponse) : PositionResult
|
|
123
|
-
data class Failure(val error: LocationError) : PositionResult
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private data class PositionRequest(
|
|
127
|
-
val id: UUID,
|
|
128
|
-
val resolver: (PositionResult) -> Unit,
|
|
129
|
-
val options: ParsedOptions,
|
|
130
|
-
val handler: Handler,
|
|
131
|
-
val providers: List<String>,
|
|
132
|
-
val deadlineElapsedRealtime: Long,
|
|
133
|
-
var providerIndex: Int = 0,
|
|
134
|
-
var cancellationSignal: CancellationSignal? = null
|
|
135
|
-
) {
|
|
136
|
-
fun remainingTimeoutMillis(): Long {
|
|
137
|
-
return (deadlineElapsedRealtime - SystemClock.elapsedRealtime()).coerceAtLeast(0L)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
47
|
// MARK: - Properties
|
|
142
48
|
|
|
143
49
|
private var configuration: GeolocationConfiguration? = null
|
|
@@ -155,6 +61,14 @@ class NitroGeolocation(
|
|
|
155
61
|
private val fusedLocationClient by lazy {
|
|
156
62
|
LocationServices.getFusedLocationProviderClient(reactContext)
|
|
157
63
|
}
|
|
64
|
+
private val fusedLocationProvider by lazy {
|
|
65
|
+
AndroidFusedLocationProvider(
|
|
66
|
+
fusedLocationClient = fusedLocationClient,
|
|
67
|
+
isCachedLocationValid = ::isCachedLocationValid,
|
|
68
|
+
effectiveMaximumAge = ::effectiveMaximumAge,
|
|
69
|
+
locationToPosition = ::locationToPosition
|
|
70
|
+
)
|
|
71
|
+
}
|
|
158
72
|
private val headingManager: AndroidHeadingManager by lazy {
|
|
159
73
|
AndroidHeadingManager(
|
|
160
74
|
context = reactContext,
|
|
@@ -181,15 +95,7 @@ class NitroGeolocation(
|
|
|
181
95
|
// Location listener for watch subscriptions
|
|
182
96
|
private var watchLocationListener: LocationListener? = null
|
|
183
97
|
private var fusedWatchLocationCallback: LocationCallback? = null
|
|
184
|
-
private
|
|
185
|
-
|
|
186
|
-
// Error codes
|
|
187
|
-
private val INTERNAL_ERROR = -1.0
|
|
188
|
-
private val PERMISSION_DENIED = 1.0
|
|
189
|
-
private val POSITION_UNAVAILABLE = 2.0
|
|
190
|
-
private val TIMEOUT = 3.0
|
|
191
|
-
private val PLAY_SERVICE_NOT_AVAILABLE = 4.0
|
|
192
|
-
private val SETTINGS_NOT_SATISFIED = 5.0
|
|
98
|
+
private val watchLocationGeneration = AtomicLong(0L)
|
|
193
99
|
|
|
194
100
|
// MARK: - Configuration
|
|
195
101
|
|
|
@@ -227,6 +133,15 @@ class NitroGeolocation(
|
|
|
227
133
|
return
|
|
228
134
|
}
|
|
229
135
|
|
|
136
|
+
val permissionAware = activity as? PermissionAwareActivity
|
|
137
|
+
if (permissionAware == null) {
|
|
138
|
+
error?.invoke(createLocationError(
|
|
139
|
+
INTERNAL_ERROR,
|
|
140
|
+
"Current activity cannot request permissions"
|
|
141
|
+
))
|
|
142
|
+
return
|
|
143
|
+
}
|
|
144
|
+
|
|
230
145
|
// Queue resolver
|
|
231
146
|
pendingPermissionResolvers.add(success)
|
|
232
147
|
|
|
@@ -236,10 +151,10 @@ class NitroGeolocation(
|
|
|
236
151
|
Manifest.permission.ACCESS_COARSE_LOCATION
|
|
237
152
|
)
|
|
238
153
|
|
|
239
|
-
|
|
240
|
-
activity,
|
|
154
|
+
permissionAware.requestPermissions(
|
|
241
155
|
permissions,
|
|
242
|
-
PERMISSION_REQUEST_CODE
|
|
156
|
+
PERMISSION_REQUEST_CODE,
|
|
157
|
+
createPermissionListener()
|
|
243
158
|
)
|
|
244
159
|
}
|
|
245
160
|
|
|
@@ -272,36 +187,26 @@ class NitroGeolocation(
|
|
|
272
187
|
return promise
|
|
273
188
|
}
|
|
274
189
|
|
|
275
|
-
if (
|
|
276
|
-
if (!isGooglePlayServicesAvailable()) {
|
|
277
|
-
promise.resolve(createLocationAvailability(false, "playServicesUnavailable"))
|
|
278
|
-
return promise
|
|
279
|
-
}
|
|
280
|
-
|
|
190
|
+
if (currentProviderRoute(isGooglePlayServicesAvailable()) == AndroidProviderRoute.FUSED) {
|
|
281
191
|
fusedLocationClient.locationAvailability
|
|
282
192
|
.addOnSuccessListener { availability ->
|
|
283
|
-
|
|
284
|
-
createLocationAvailability(
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
)
|
|
193
|
+
if (availability.isLocationAvailable) {
|
|
194
|
+
promise.resolve(createLocationAvailability(true, null))
|
|
195
|
+
return@addOnSuccessListener
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
promise.resolve(getPlatformLocationAvailability())
|
|
289
199
|
}
|
|
290
|
-
.addOnFailureListener {
|
|
291
|
-
promise.resolve(
|
|
292
|
-
false,
|
|
293
|
-
"fusedLocationUnavailable: ${exception.message ?: "unknown error"}"
|
|
294
|
-
))
|
|
200
|
+
.addOnFailureListener {
|
|
201
|
+
promise.resolve(getPlatformLocationAvailability())
|
|
295
202
|
}
|
|
296
203
|
.addOnCanceledListener {
|
|
297
|
-
promise.resolve(
|
|
204
|
+
promise.resolve(getPlatformLocationAvailability())
|
|
298
205
|
}
|
|
299
206
|
return promise
|
|
300
207
|
}
|
|
301
208
|
|
|
302
|
-
|
|
303
|
-
val reason = if (providers.isEmpty()) "noLocationProvider" else null
|
|
304
|
-
promise.resolve(createLocationAvailability(providers.isNotEmpty(), reason))
|
|
209
|
+
promise.resolve(getPlatformLocationAvailability())
|
|
305
210
|
return promise
|
|
306
211
|
}
|
|
307
212
|
|
|
@@ -362,16 +267,41 @@ class NitroGeolocation(
|
|
|
362
267
|
error?.invoke(permissionError)
|
|
363
268
|
return
|
|
364
269
|
}
|
|
365
|
-
|
|
366
|
-
|
|
270
|
+
val deadlineElapsedRealtime = createRequestDeadlineElapsedRealtime(parsedOptions.timeout)
|
|
271
|
+
if (currentProviderRoute(isGooglePlayServicesAvailable()) == AndroidProviderRoute.FUSED) {
|
|
272
|
+
fusedLocationProvider.getCurrentPosition(
|
|
273
|
+
success,
|
|
274
|
+
{ fusedError ->
|
|
275
|
+
runAndroidCurrentPositionFallbackAfterFusedFailure(
|
|
276
|
+
locationProvider = configuration?.locationProvider,
|
|
277
|
+
runPlatformFallback = {
|
|
278
|
+
getCurrentPositionWithPlatform(
|
|
279
|
+
success,
|
|
280
|
+
error,
|
|
281
|
+
parsedOptions,
|
|
282
|
+
deadlineElapsedRealtime
|
|
283
|
+
)
|
|
284
|
+
},
|
|
285
|
+
failWithoutFallback = {
|
|
286
|
+
error?.invoke(fusedError)
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
},
|
|
290
|
+
parsedOptions,
|
|
291
|
+
deadlineElapsedRealtime
|
|
292
|
+
)
|
|
367
293
|
return
|
|
368
294
|
}
|
|
369
295
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return
|
|
373
|
-
}
|
|
296
|
+
getCurrentPositionWithPlatform(success, error, parsedOptions, deadlineElapsedRealtime)
|
|
297
|
+
}
|
|
374
298
|
|
|
299
|
+
private fun getCurrentPositionWithPlatform(
|
|
300
|
+
success: (GeolocationResponse) -> Unit,
|
|
301
|
+
error: ((LocationError) -> Unit)?,
|
|
302
|
+
parsedOptions: ParsedOptions,
|
|
303
|
+
deadlineElapsedRealtime: Long = createRequestDeadlineElapsedRealtime(parsedOptions.timeout)
|
|
304
|
+
) {
|
|
375
305
|
val providers = getValidProviders(parsedOptions)
|
|
376
306
|
if (providers.isEmpty()) {
|
|
377
307
|
error?.invoke(createNoLocationProviderError(parsedOptions))
|
|
@@ -384,8 +314,13 @@ class NitroGeolocation(
|
|
|
384
314
|
return
|
|
385
315
|
}
|
|
386
316
|
|
|
317
|
+
if (remainingTimeoutMillis(deadlineElapsedRealtime) <= 0L) {
|
|
318
|
+
error?.invoke(createPositionTimeoutError(parsedOptions))
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
|
|
387
322
|
// Request fresh location
|
|
388
|
-
requestFreshLocation(providers, parsedOptions) { result ->
|
|
323
|
+
requestFreshLocation(providers, parsedOptions, deadlineElapsedRealtime) { result ->
|
|
389
324
|
when (result) {
|
|
390
325
|
is PositionResult.Success -> success(result.position)
|
|
391
326
|
is PositionResult.Failure -> error?.invoke(result.error)
|
|
@@ -417,16 +352,33 @@ class NitroGeolocation(
|
|
|
417
352
|
error?.invoke(permissionError)
|
|
418
353
|
return
|
|
419
354
|
}
|
|
420
|
-
if (
|
|
421
|
-
|
|
355
|
+
if (currentProviderRoute(isGooglePlayServicesAvailable()) == AndroidProviderRoute.FUSED) {
|
|
356
|
+
fusedLocationProvider.getLastKnownPosition(
|
|
357
|
+
success,
|
|
358
|
+
{ fusedError ->
|
|
359
|
+
runAndroidLastKnownPositionFallbackAfterFusedFailure(
|
|
360
|
+
locationProvider = configuration?.locationProvider,
|
|
361
|
+
runPlatformFallback = {
|
|
362
|
+
getLastKnownPositionWithPlatform(success, error, parsedOptions)
|
|
363
|
+
},
|
|
364
|
+
failWithoutFallback = {
|
|
365
|
+
error?.invoke(fusedError)
|
|
366
|
+
}
|
|
367
|
+
)
|
|
368
|
+
},
|
|
369
|
+
parsedOptions
|
|
370
|
+
)
|
|
422
371
|
return
|
|
423
372
|
}
|
|
424
373
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return
|
|
428
|
-
}
|
|
374
|
+
getLastKnownPositionWithPlatform(success, error, parsedOptions)
|
|
375
|
+
}
|
|
429
376
|
|
|
377
|
+
private fun getLastKnownPositionWithPlatform(
|
|
378
|
+
success: (GeolocationResponse) -> Unit,
|
|
379
|
+
error: ((LocationError) -> Unit)?,
|
|
380
|
+
parsedOptions: ParsedOptions
|
|
381
|
+
) {
|
|
430
382
|
val providers = getValidProviders(parsedOptions)
|
|
431
383
|
if (providers.isEmpty()) {
|
|
432
384
|
error?.invoke(createNoLocationProviderError(parsedOptions))
|
|
@@ -466,7 +418,7 @@ class NitroGeolocation(
|
|
|
466
418
|
@Suppress("DEPRECATION")
|
|
467
419
|
geocoder.getFromLocationName(query, GEOCODER_MAX_RESULTS)
|
|
468
420
|
.orEmpty()
|
|
469
|
-
.mapNotNull {
|
|
421
|
+
.mapNotNull { it.toGeocodedLocation() }
|
|
470
422
|
.toTypedArray()
|
|
471
423
|
}
|
|
472
424
|
}
|
|
@@ -491,7 +443,7 @@ class NitroGeolocation(
|
|
|
491
443
|
GEOCODER_MAX_RESULTS
|
|
492
444
|
)
|
|
493
445
|
.orEmpty()
|
|
494
|
-
.map {
|
|
446
|
+
.map { it.toReverseGeocodedAddress() }
|
|
495
447
|
.toTypedArray()
|
|
496
448
|
}
|
|
497
449
|
}
|
|
@@ -730,8 +682,13 @@ class NitroGeolocation(
|
|
|
730
682
|
return null
|
|
731
683
|
}
|
|
732
684
|
|
|
733
|
-
|
|
734
|
-
|
|
685
|
+
private fun createPermissionListener() =
|
|
686
|
+
PermissionListener { requestCode, _, grantResults ->
|
|
687
|
+
onPermissionResult(requestCode, grantResults)
|
|
688
|
+
requestCode == PERMISSION_REQUEST_CODE
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
private fun onPermissionResult(requestCode: Int, grantResults: IntArray) {
|
|
735
692
|
if (requestCode != PERMISSION_REQUEST_CODE) return
|
|
736
693
|
|
|
737
694
|
val granted = grantResults.isNotEmpty() && grantResults.any { it == PackageManager.PERMISSION_GRANTED }
|
|
@@ -746,10 +703,13 @@ class NitroGeolocation(
|
|
|
746
703
|
|
|
747
704
|
// MARK: - Helper Functions - Provider Selection
|
|
748
705
|
|
|
749
|
-
private fun
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
return
|
|
706
|
+
private fun currentProviderRoute(
|
|
707
|
+
googlePlayServicesAvailable: Boolean
|
|
708
|
+
): AndroidProviderRoute {
|
|
709
|
+
return selectAndroidProviderRoute(
|
|
710
|
+
locationProvider = configuration?.locationProvider,
|
|
711
|
+
googlePlayServicesAvailable = googlePlayServicesAvailable
|
|
712
|
+
)
|
|
753
713
|
}
|
|
754
714
|
|
|
755
715
|
private fun isGooglePlayServicesAvailable(): Boolean {
|
|
@@ -757,6 +717,12 @@ class NitroGeolocation(
|
|
|
757
717
|
.isGooglePlayServicesAvailable(reactContext) == ConnectionResult.SUCCESS
|
|
758
718
|
}
|
|
759
719
|
|
|
720
|
+
private fun getPlatformLocationAvailability(): LocationAvailability {
|
|
721
|
+
val providers = getValidProviders(resolveAndroidAccuracy(null, enableHighAccuracy = false))
|
|
722
|
+
val reason = if (providers.isEmpty()) "noLocationProvider" else null
|
|
723
|
+
return createLocationAvailability(providers.isNotEmpty(), reason)
|
|
724
|
+
}
|
|
725
|
+
|
|
760
726
|
private fun getValidProvider(accuracy: AndroidAccuracyResolution): String? {
|
|
761
727
|
return getValidProviders(accuracy).firstOrNull()
|
|
762
728
|
}
|
|
@@ -868,138 +834,12 @@ class NitroGeolocation(
|
|
|
868
834
|
return bestLocation
|
|
869
835
|
}
|
|
870
836
|
|
|
871
|
-
private fun getCurrentPositionWithFused(
|
|
872
|
-
success: (GeolocationResponse) -> Unit,
|
|
873
|
-
error: ((LocationError) -> Unit)?,
|
|
874
|
-
options: ParsedOptions
|
|
875
|
-
) {
|
|
876
|
-
if (effectiveMaximumAge(options) > 0.0) {
|
|
877
|
-
getFusedCachedLocation(options) { cachedLocation ->
|
|
878
|
-
if (cachedLocation != null) {
|
|
879
|
-
success(locationToPosition(cachedLocation))
|
|
880
|
-
return@getFusedCachedLocation
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
requestFusedFreshLocation(success, error, options)
|
|
884
|
-
}
|
|
885
|
-
return
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
requestFusedFreshLocation(success, error, options)
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
private fun getLastKnownPositionWithFused(
|
|
892
|
-
success: (GeolocationResponse) -> Unit,
|
|
893
|
-
error: ((LocationError) -> Unit)?,
|
|
894
|
-
options: ParsedOptions
|
|
895
|
-
) {
|
|
896
|
-
getFusedCachedLocation(options) { cachedLocation ->
|
|
897
|
-
if (cachedLocation != null) {
|
|
898
|
-
success(locationToPosition(cachedLocation))
|
|
899
|
-
return@getFusedCachedLocation
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
error?.invoke(createLocationError(
|
|
903
|
-
POSITION_UNAVAILABLE,
|
|
904
|
-
"No cached location available"
|
|
905
|
-
))
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
private fun getFusedCachedLocation(
|
|
910
|
-
options: ParsedOptions,
|
|
911
|
-
completion: (Location?) -> Unit
|
|
912
|
-
) {
|
|
913
|
-
// Fused lastLocation is not requested with LocationRequest granularity,
|
|
914
|
-
// so it cannot prove that a cached fix satisfies coarse-only callers.
|
|
915
|
-
if (options.granularity == AndroidGranularity.COARSE) {
|
|
916
|
-
completion(null)
|
|
917
|
-
return
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
try {
|
|
921
|
-
fusedLocationClient.lastLocation
|
|
922
|
-
.addOnSuccessListener { location ->
|
|
923
|
-
completion(location?.takeIf { isCachedLocationValid(it, options) })
|
|
924
|
-
}
|
|
925
|
-
.addOnFailureListener {
|
|
926
|
-
completion(null)
|
|
927
|
-
}
|
|
928
|
-
.addOnCanceledListener {
|
|
929
|
-
completion(null)
|
|
930
|
-
}
|
|
931
|
-
} catch (e: SecurityException) {
|
|
932
|
-
completion(null)
|
|
933
|
-
}
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
private fun requestFusedFreshLocation(
|
|
937
|
-
success: (GeolocationResponse) -> Unit,
|
|
938
|
-
error: ((LocationError) -> Unit)?,
|
|
939
|
-
options: ParsedOptions
|
|
940
|
-
) {
|
|
941
|
-
val handler = Handler(Looper.getMainLooper())
|
|
942
|
-
val didComplete = AtomicBoolean(false)
|
|
943
|
-
lateinit var callback: LocationCallback
|
|
944
|
-
|
|
945
|
-
fun complete(result: PositionResult) {
|
|
946
|
-
if (!didComplete.compareAndSet(false, true)) return
|
|
947
|
-
|
|
948
|
-
handler.removeCallbacksAndMessages(null)
|
|
949
|
-
try {
|
|
950
|
-
fusedLocationClient.removeLocationUpdates(callback)
|
|
951
|
-
} catch (_: Exception) {
|
|
952
|
-
// Ignore cleanup races.
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
when (result) {
|
|
956
|
-
is PositionResult.Success -> success(result.position)
|
|
957
|
-
is PositionResult.Failure -> error?.invoke(result.error)
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
callback = object : LocationCallback() {
|
|
962
|
-
override fun onLocationResult(result: LocationResult) {
|
|
963
|
-
val location = result.lastLocation
|
|
964
|
-
if (location != null) {
|
|
965
|
-
complete(PositionResult.Success(locationToPosition(location)))
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
val timeoutRunnable = Runnable {
|
|
971
|
-
complete(PositionResult.Failure(createPositionTimeoutError(options)))
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
try {
|
|
975
|
-
fusedLocationClient.requestLocationUpdates(
|
|
976
|
-
buildFusedLocationRequest(
|
|
977
|
-
options,
|
|
978
|
-
maxUpdatesOverride = 1,
|
|
979
|
-
includeDistanceFilter = false
|
|
980
|
-
),
|
|
981
|
-
callback,
|
|
982
|
-
Looper.getMainLooper()
|
|
983
|
-
)
|
|
984
|
-
handler.postDelayed(timeoutRunnable, coerceTimeoutMillis(options.timeout))
|
|
985
|
-
} catch (e: SecurityException) {
|
|
986
|
-
complete(PositionResult.Failure(createLocationError(
|
|
987
|
-
PERMISSION_DENIED,
|
|
988
|
-
"Security exception: ${e.message}"
|
|
989
|
-
)))
|
|
990
|
-
} catch (e: Exception) {
|
|
991
|
-
complete(PositionResult.Failure(createLocationError(
|
|
992
|
-
POSITION_UNAVAILABLE,
|
|
993
|
-
"Unable to request fused location: ${e.message}"
|
|
994
|
-
)))
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
|
|
998
837
|
// MARK: - Helper Functions - Request Fresh Location
|
|
999
838
|
|
|
1000
839
|
private fun requestFreshLocation(
|
|
1001
840
|
providers: List<String>,
|
|
1002
841
|
options: ParsedOptions,
|
|
842
|
+
deadlineElapsedRealtime: Long = createRequestDeadlineElapsedRealtime(options.timeout),
|
|
1003
843
|
resolver: (PositionResult) -> Unit
|
|
1004
844
|
) {
|
|
1005
845
|
val id = UUID.randomUUID()
|
|
@@ -1011,7 +851,7 @@ class NitroGeolocation(
|
|
|
1011
851
|
options = options,
|
|
1012
852
|
handler = handler,
|
|
1013
853
|
providers = providers,
|
|
1014
|
-
deadlineElapsedRealtime =
|
|
854
|
+
deadlineElapsedRealtime = deadlineElapsedRealtime
|
|
1015
855
|
)
|
|
1016
856
|
|
|
1017
857
|
pendingPositionRequests[id] = request
|
|
@@ -1037,9 +877,9 @@ class NitroGeolocation(
|
|
|
1037
877
|
return
|
|
1038
878
|
}
|
|
1039
879
|
|
|
1040
|
-
// Android's getCurrentLocation may resolve a recent historical fix.
|
|
1041
|
-
// means callers explicitly asked us to wait for a fresh
|
|
1042
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && request.options
|
|
880
|
+
// Android's getCurrentLocation may resolve a recent historical fix. An effective
|
|
881
|
+
// maximum age of 0 means callers explicitly asked us to wait for a fresh update.
|
|
882
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && effectiveMaximumAge(request.options) > 0.0) {
|
|
1043
883
|
requestCurrentLocationModern(provider, requestId, request.handler, remainingTimeoutMillis)
|
|
1044
884
|
} else {
|
|
1045
885
|
requestCurrentLocationLegacy(provider, requestId, request.handler, remainingTimeoutMillis)
|
|
@@ -1070,14 +910,21 @@ class NitroGeolocation(
|
|
|
1070
910
|
|
|
1071
911
|
val request = pendingPositionRequests[requestId]
|
|
1072
912
|
if (request != null) {
|
|
1073
|
-
if (location != null) {
|
|
913
|
+
if (location != null && isCachedLocationValid(location, request.options)) {
|
|
1074
914
|
pendingPositionRequests.remove(requestId)
|
|
1075
915
|
val position = locationToPosition(location)
|
|
1076
916
|
request.resolver(PositionResult.Success(position))
|
|
917
|
+
} else if (location != null) {
|
|
918
|
+
retryCurrentLocationLegacyAfterStaleModern(
|
|
919
|
+
provider,
|
|
920
|
+
requestId,
|
|
921
|
+
handler,
|
|
922
|
+
request
|
|
923
|
+
)
|
|
1077
924
|
} else {
|
|
1078
925
|
handleProviderFailure(requestId, createLocationError(
|
|
1079
926
|
POSITION_UNAVAILABLE,
|
|
1080
|
-
"Unable to get location"
|
|
927
|
+
"Unable to get fresh location"
|
|
1081
928
|
))
|
|
1082
929
|
}
|
|
1083
930
|
}
|
|
@@ -1096,6 +943,24 @@ class NitroGeolocation(
|
|
|
1096
943
|
}
|
|
1097
944
|
}
|
|
1098
945
|
|
|
946
|
+
private fun retryCurrentLocationLegacyAfterStaleModern(
|
|
947
|
+
provider: String,
|
|
948
|
+
requestId: UUID,
|
|
949
|
+
handler: Handler,
|
|
950
|
+
request: PositionRequest
|
|
951
|
+
) {
|
|
952
|
+
request.cancellationSignal?.cancel()
|
|
953
|
+
request.cancellationSignal = null
|
|
954
|
+
|
|
955
|
+
val remainingTimeoutMillis = request.remainingTimeoutMillis()
|
|
956
|
+
if (remainingTimeoutMillis <= 0L) {
|
|
957
|
+
handlePositionTimeout(requestId)
|
|
958
|
+
return
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
requestCurrentLocationLegacy(provider, requestId, handler, remainingTimeoutMillis)
|
|
962
|
+
}
|
|
963
|
+
|
|
1099
964
|
private fun requestCurrentLocationLegacy(
|
|
1100
965
|
provider: String,
|
|
1101
966
|
requestId: UUID,
|
|
@@ -1234,31 +1099,41 @@ class NitroGeolocation(
|
|
|
1234
1099
|
// MARK: - Helper Functions - Watch Position
|
|
1235
1100
|
|
|
1236
1101
|
private fun startWatchingLocation() {
|
|
1237
|
-
|
|
1238
|
-
notifyWatchPlayServicesUnavailable()
|
|
1239
|
-
return
|
|
1240
|
-
}
|
|
1102
|
+
val generation = watchLocationGeneration.get()
|
|
1241
1103
|
|
|
1242
|
-
if (
|
|
1243
|
-
startWatchingFusedLocation()
|
|
1104
|
+
if (currentProviderRoute(isGooglePlayServicesAvailable()) == AndroidProviderRoute.FUSED) {
|
|
1105
|
+
startWatchingFusedLocation(generation)
|
|
1244
1106
|
return
|
|
1245
1107
|
}
|
|
1246
1108
|
|
|
1109
|
+
startWatchingPlatformLocation(generation)
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
private fun isActiveWatchGeneration(generation: Long): Boolean {
|
|
1113
|
+
return watchSubscriptions.isNotEmpty() && watchLocationGeneration.get() == generation
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
private fun startWatchingPlatformLocation(generation: Long) {
|
|
1117
|
+
if (!isActiveWatchGeneration(generation)) return
|
|
1118
|
+
|
|
1247
1119
|
val mergedOptions = mergeWatchOptions()
|
|
1248
1120
|
val provider = getValidProvider(mergedOptions)
|
|
1249
1121
|
if (provider == null) {
|
|
1250
1122
|
notifyWatchProviderUnavailable()
|
|
1251
1123
|
return
|
|
1252
1124
|
}
|
|
1253
|
-
currentWatchProvider = provider
|
|
1254
1125
|
|
|
1255
1126
|
val listener = object : LocationListener {
|
|
1256
1127
|
override fun onLocationChanged(location: Location) {
|
|
1128
|
+
if (!isActiveWatchGeneration(generation)) return
|
|
1129
|
+
|
|
1257
1130
|
val position = locationToPosition(location)
|
|
1258
1131
|
deliverWatchPosition(position)
|
|
1259
1132
|
}
|
|
1260
1133
|
|
|
1261
1134
|
override fun onProviderDisabled(provider: String) {
|
|
1135
|
+
if (!isActiveWatchGeneration(generation)) return
|
|
1136
|
+
|
|
1262
1137
|
val error = LocationError(
|
|
1263
1138
|
code = SETTINGS_NOT_SATISFIED,
|
|
1264
1139
|
message = "Provider disabled: $provider"
|
|
@@ -1274,6 +1149,7 @@ class NitroGeolocation(
|
|
|
1274
1149
|
override fun onStatusChanged(provider: String?, status: Int, extras: android.os.Bundle?) {}
|
|
1275
1150
|
}
|
|
1276
1151
|
|
|
1152
|
+
removePlatformWatchLocationListener()
|
|
1277
1153
|
watchLocationListener = listener
|
|
1278
1154
|
|
|
1279
1155
|
try {
|
|
@@ -1296,42 +1172,53 @@ class NitroGeolocation(
|
|
|
1296
1172
|
}
|
|
1297
1173
|
}
|
|
1298
1174
|
|
|
1299
|
-
private fun startWatchingFusedLocation() {
|
|
1175
|
+
private fun startWatchingFusedLocation(generation: Long) {
|
|
1176
|
+
if (!isActiveWatchGeneration(generation)) return
|
|
1177
|
+
|
|
1300
1178
|
val mergedOptions = mergeWatchOptions()
|
|
1301
1179
|
val callback = object : LocationCallback() {
|
|
1302
1180
|
override fun onLocationResult(result: LocationResult) {
|
|
1181
|
+
if (!isActiveWatchGeneration(generation)) return
|
|
1182
|
+
|
|
1303
1183
|
val location = result.lastLocation ?: return
|
|
1304
|
-
deliverWatchPosition(locationToPosition(location))
|
|
1184
|
+
deliverWatchPosition(locationToPosition(location, LocationProviderUsed.FUSED))
|
|
1305
1185
|
}
|
|
1306
1186
|
}
|
|
1307
1187
|
|
|
1188
|
+
removeFusedWatchLocationCallback()
|
|
1308
1189
|
fusedWatchLocationCallback = callback
|
|
1309
1190
|
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
buildFusedLocationRequest(mergedOptions),
|
|
1313
|
-
callback,
|
|
1314
|
-
Looper.getMainLooper()
|
|
1315
|
-
)
|
|
1316
|
-
} catch (e: SecurityException) {
|
|
1317
|
-
val error = LocationError(
|
|
1318
|
-
code = PERMISSION_DENIED,
|
|
1319
|
-
message = "Permission denied: ${e.message}"
|
|
1320
|
-
)
|
|
1191
|
+
fun handleFusedRequestFailure(fusedError: LocationError? = null) {
|
|
1192
|
+
if (!isActiveWatchGeneration(generation)) return
|
|
1321
1193
|
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1194
|
+
removeFusedWatchLocationCallback()
|
|
1195
|
+
runAndroidWatchPositionFallbackAfterFusedFailure(
|
|
1196
|
+
locationProvider = configuration?.locationProvider,
|
|
1197
|
+
runPlatformFallback = { startWatchingPlatformLocation(generation) },
|
|
1198
|
+
failWithoutFallback = {
|
|
1199
|
+
if (fusedError != null) {
|
|
1200
|
+
notifyWatchError(fusedError)
|
|
1201
|
+
} else {
|
|
1202
|
+
notifyWatchProviderUnavailable()
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1329
1205
|
)
|
|
1330
|
-
|
|
1331
|
-
for ((_, subscription) in watchSubscriptions) {
|
|
1332
|
-
subscription.error?.invoke(error)
|
|
1333
|
-
}
|
|
1334
1206
|
}
|
|
1207
|
+
|
|
1208
|
+
fusedLocationProvider.requestWatchUpdates(
|
|
1209
|
+
options = mergedOptions,
|
|
1210
|
+
callback = callback,
|
|
1211
|
+
onInactiveStart = {
|
|
1212
|
+
if (!isActiveWatchGeneration(generation)) {
|
|
1213
|
+
try {
|
|
1214
|
+
fusedLocationClient.removeLocationUpdates(callback)
|
|
1215
|
+
} catch (e: Exception) {
|
|
1216
|
+
// Ignore
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
},
|
|
1220
|
+
onFailure = { fusedError -> handleFusedRequestFailure(fusedError) }
|
|
1221
|
+
)
|
|
1335
1222
|
}
|
|
1336
1223
|
|
|
1337
1224
|
private fun mergeWatchOptions(): ParsedOptions {
|
|
@@ -1418,9 +1305,9 @@ class NitroGeolocation(
|
|
|
1418
1305
|
}
|
|
1419
1306
|
}
|
|
1420
1307
|
|
|
1421
|
-
private fun
|
|
1308
|
+
private fun notifyWatchError(error: LocationError) {
|
|
1422
1309
|
for ((_, subscription) in watchSubscriptions) {
|
|
1423
|
-
subscription.error?.invoke(
|
|
1310
|
+
subscription.error?.invoke(error)
|
|
1424
1311
|
}
|
|
1425
1312
|
}
|
|
1426
1313
|
|
|
@@ -1448,6 +1335,12 @@ class NitroGeolocation(
|
|
|
1448
1335
|
}
|
|
1449
1336
|
|
|
1450
1337
|
private fun stopWatchingLocation() {
|
|
1338
|
+
watchLocationGeneration.incrementAndGet()
|
|
1339
|
+
removePlatformWatchLocationListener()
|
|
1340
|
+
removeFusedWatchLocationCallback()
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
private fun removePlatformWatchLocationListener() {
|
|
1451
1344
|
watchLocationListener?.let { listener ->
|
|
1452
1345
|
try {
|
|
1453
1346
|
locationManager.removeUpdates(listener)
|
|
@@ -1455,6 +1348,10 @@ class NitroGeolocation(
|
|
|
1455
1348
|
// Ignore
|
|
1456
1349
|
}
|
|
1457
1350
|
}
|
|
1351
|
+
watchLocationListener = null
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
private fun removeFusedWatchLocationCallback() {
|
|
1458
1355
|
fusedWatchLocationCallback?.let { callback ->
|
|
1459
1356
|
try {
|
|
1460
1357
|
fusedLocationClient.removeLocationUpdates(callback)
|
|
@@ -1462,9 +1359,7 @@ class NitroGeolocation(
|
|
|
1462
1359
|
// Ignore
|
|
1463
1360
|
}
|
|
1464
1361
|
}
|
|
1465
|
-
watchLocationListener = null
|
|
1466
1362
|
fusedWatchLocationCallback = null
|
|
1467
|
-
currentWatchProvider = null
|
|
1468
1363
|
}
|
|
1469
1364
|
|
|
1470
1365
|
private fun restartWatchingLocation() {
|
|
@@ -1474,67 +1369,13 @@ class NitroGeolocation(
|
|
|
1474
1369
|
|
|
1475
1370
|
// MARK: - Helper Functions - Conversion
|
|
1476
1371
|
|
|
1477
|
-
private fun locationToPosition(
|
|
1372
|
+
private fun locationToPosition(
|
|
1373
|
+
location: Location,
|
|
1374
|
+
providerOverride: LocationProviderUsed? = null
|
|
1375
|
+
): GeolocationResponse {
|
|
1478
1376
|
lastLocation = location
|
|
1479
1377
|
|
|
1480
|
-
|
|
1481
|
-
latitude = location.latitude,
|
|
1482
|
-
longitude = location.longitude,
|
|
1483
|
-
altitude = location.altitudeValue(),
|
|
1484
|
-
accuracy = location.accuracy.toDouble(),
|
|
1485
|
-
altitudeAccuracy = location.altitudeAccuracyValue(),
|
|
1486
|
-
heading = location.headingValue(),
|
|
1487
|
-
speed = location.speedValue()
|
|
1488
|
-
)
|
|
1489
|
-
|
|
1490
|
-
return GeolocationResponse(
|
|
1491
|
-
coords = coords,
|
|
1492
|
-
timestamp = location.time.toDouble(),
|
|
1493
|
-
mocked = location.isMocked(),
|
|
1494
|
-
provider = location.providerUsed()
|
|
1495
|
-
)
|
|
1496
|
-
}
|
|
1497
|
-
|
|
1498
|
-
private fun geocodedAddressToLocation(address: Address): GeocodedLocation? {
|
|
1499
|
-
if (!address.hasLatitude() || !address.hasLongitude()) {
|
|
1500
|
-
return null
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
return GeocodedLocation(
|
|
1504
|
-
latitude = address.latitude,
|
|
1505
|
-
longitude = address.longitude,
|
|
1506
|
-
accuracy = null
|
|
1507
|
-
)
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
private fun addressToReverseGeocodedAddress(address: Address): ReverseGeocodedAddress {
|
|
1511
|
-
return ReverseGeocodedAddress(
|
|
1512
|
-
country = address.countryName.nonBlankOrNull(),
|
|
1513
|
-
region = address.adminArea.nonBlankOrNull(),
|
|
1514
|
-
city = (address.locality ?: address.subAdminArea).nonBlankOrNull(),
|
|
1515
|
-
district = address.subLocality.nonBlankOrNull(),
|
|
1516
|
-
street = formatStreet(address),
|
|
1517
|
-
postalCode = address.postalCode.nonBlankOrNull(),
|
|
1518
|
-
formattedAddress = formatAddressLines(address)
|
|
1519
|
-
)
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
|
-
private fun formatStreet(address: Address): String? {
|
|
1523
|
-
return listOf(address.subThoroughfare, address.thoroughfare)
|
|
1524
|
-
.mapNotNull { it.nonBlankOrNull() }
|
|
1525
|
-
.joinToString(" ")
|
|
1526
|
-
.nonBlankOrNull()
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
private fun formatAddressLines(address: Address): String? {
|
|
1530
|
-
if (address.maxAddressLineIndex < 0) {
|
|
1531
|
-
return null
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
return (0..address.maxAddressLineIndex)
|
|
1535
|
-
.mapNotNull { index -> address.getAddressLine(index).nonBlankOrNull() }
|
|
1536
|
-
.joinToString(", ")
|
|
1537
|
-
.nonBlankOrNull()
|
|
1378
|
+
return location.toGeolocationResponse(providerOverride)
|
|
1538
1379
|
}
|
|
1539
1380
|
|
|
1540
1381
|
private fun validateGeocodingCoordinates(coords: GeocodingCoordinates): LocationError? {
|
|
@@ -1593,107 +1434,9 @@ class NitroGeolocation(
|
|
|
1593
1434
|
}.start()
|
|
1594
1435
|
}
|
|
1595
1436
|
|
|
1596
|
-
private fun createLocationAvailability(
|
|
1597
|
-
available: Boolean,
|
|
1598
|
-
reason: String?
|
|
1599
|
-
): LocationAvailability {
|
|
1600
|
-
return LocationAvailability(
|
|
1601
|
-
available = available,
|
|
1602
|
-
reason = reason
|
|
1603
|
-
)
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
private fun createLocationError(code: Double, message: String): LocationError {
|
|
1607
|
-
return LocationError(
|
|
1608
|
-
code = code,
|
|
1609
|
-
message = message
|
|
1610
|
-
)
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
|
-
private fun createPlayServicesUnavailableError(): LocationError {
|
|
1614
|
-
return createLocationError(
|
|
1615
|
-
PLAY_SERVICE_NOT_AVAILABLE,
|
|
1616
|
-
"Google Play Services location provider is not available."
|
|
1617
|
-
)
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
private fun createPositionTimeoutError(options: ParsedOptions): LocationError {
|
|
1621
|
-
val timeoutSeconds = options.timeout / 1000.0
|
|
1622
|
-
val message = String.format("Unable to fetch location within %.1fs.", timeoutSeconds)
|
|
1623
|
-
return createLocationError(TIMEOUT, message)
|
|
1624
|
-
}
|
|
1625
|
-
|
|
1626
|
-
private fun createRequestDeadlineElapsedRealtime(timeout: Double): Long {
|
|
1627
|
-
val now = SystemClock.elapsedRealtime()
|
|
1628
|
-
val timeoutMillis = coerceTimeoutMillis(timeout)
|
|
1629
|
-
val maxTimeoutMillis = Long.MAX_VALUE - now
|
|
1630
|
-
|
|
1631
|
-
return if (timeoutMillis >= maxTimeoutMillis) {
|
|
1632
|
-
Long.MAX_VALUE
|
|
1633
|
-
} else {
|
|
1634
|
-
now + timeoutMillis
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
|
|
1638
|
-
private fun coerceTimeoutMillis(timeout: Double): Long {
|
|
1639
|
-
return when {
|
|
1640
|
-
timeout.isNaN() || timeout <= 0.0 -> 0L
|
|
1641
|
-
timeout.isInfinite() || timeout >= Long.MAX_VALUE.toDouble() -> Long.MAX_VALUE
|
|
1642
|
-
else -> timeout.toLong()
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
|
-
private fun buildFusedLocationRequest(
|
|
1647
|
-
options: ParsedOptions,
|
|
1648
|
-
maxUpdatesOverride: Int? = null,
|
|
1649
|
-
includeDistanceFilter: Boolean = true
|
|
1650
|
-
): GmsLocationRequest {
|
|
1651
|
-
val builder = GmsLocationRequest
|
|
1652
|
-
.Builder(options.androidAccuracy.gmsPriority(), coercePositiveMillis(options.interval))
|
|
1653
|
-
.setMinUpdateIntervalMillis(coercePositiveMillis(options.fastestInterval))
|
|
1654
|
-
.setGranularity(options.granularity.gmsGranularity())
|
|
1655
|
-
.setWaitForAccurateLocation(options.waitForAccurateLocation)
|
|
1656
|
-
.setMaxUpdateDelayMillis(coerceNonNegativeMillis(options.maxUpdateDelay))
|
|
1657
|
-
|
|
1658
|
-
if (includeDistanceFilter) {
|
|
1659
|
-
builder.setMinUpdateDistanceMeters(options.distanceFilter.toFloat())
|
|
1660
|
-
}
|
|
1661
|
-
|
|
1662
|
-
options.maxUpdateAge?.let { value ->
|
|
1663
|
-
builder.setMaxUpdateAgeMillis(coerceNonNegativeMillis(value))
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
val maxUpdates = maxUpdatesOverride ?: options.maxUpdates
|
|
1667
|
-
if (maxUpdates != null) {
|
|
1668
|
-
builder.setMaxUpdates(maxUpdates)
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
return builder.build()
|
|
1672
|
-
}
|
|
1673
|
-
|
|
1674
|
-
private fun coercePositiveMillis(value: Double): Long {
|
|
1675
|
-
return when {
|
|
1676
|
-
value.isNaN() || value <= 0.0 -> 1L
|
|
1677
|
-
value.isInfinite() || value >= Long.MAX_VALUE.toDouble() -> Long.MAX_VALUE
|
|
1678
|
-
else -> value.toLong()
|
|
1679
|
-
}
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
private fun coerceNonNegativeMillis(value: Double): Long {
|
|
1683
|
-
return when {
|
|
1684
|
-
value.isNaN() || value <= 0.0 -> 0L
|
|
1685
|
-
value.isInfinite() || value >= Long.MAX_VALUE.toDouble() -> Long.MAX_VALUE
|
|
1686
|
-
else -> value.toLong()
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
1437
|
companion object {
|
|
1691
1438
|
private const val PERMISSION_REQUEST_CODE = 8947
|
|
1692
1439
|
private const val GEOCODER_MAX_RESULTS = 5
|
|
1693
1440
|
private const val TWO_MINUTES_MS = 2 * 60 * 1000L
|
|
1694
1441
|
}
|
|
1695
1442
|
}
|
|
1696
|
-
|
|
1697
|
-
private fun String?.nonBlankOrNull(): String? {
|
|
1698
|
-
return this?.trim()?.takeIf { it.isNotEmpty() }
|
|
1699
|
-
}
|