expo-location 16.4.0 → 16.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/android/build.gradle +5 -6
  3. package/android/src/main/AndroidManifest.xml +1 -0
  4. package/android/src/main/java/expo/modules/location/LocationActivityResultListener.kt +5 -0
  5. package/android/src/main/java/expo/modules/location/LocationExceptions.kt +57 -0
  6. package/android/src/main/java/expo/modules/location/LocationHelpers.kt +220 -0
  7. package/android/src/main/java/expo/modules/location/LocationModule.kt +820 -0
  8. package/android/src/main/java/expo/modules/location/LocationRequestCallbacks.kt +11 -0
  9. package/android/src/main/java/expo/modules/location/records/LocationArguments.kt +101 -0
  10. package/android/src/main/java/expo/modules/location/records/LocationResults.kt +202 -0
  11. package/android/src/main/java/expo/modules/location/services/LocationTaskService.kt +120 -0
  12. package/android/src/main/java/expo/modules/location/taskConsumers/GeofencingTaskConsumer.kt +245 -0
  13. package/android/src/main/java/expo/modules/location/taskConsumers/LocationTaskConsumer.kt +322 -0
  14. package/expo-location-0.0.1-canary-20231129-c0ec023.tgz +0 -0
  15. package/expo-location-0.0.1-canary-20231130-c8a9bf9.tgz +0 -0
  16. package/expo-location-0.0.1-canary-20231130-ede75a7-1.tgz +0 -0
  17. package/expo-location-0.0.1-canary-20231130-ede75a7.tgz +0 -0
  18. package/expo-module.config.json +6 -0
  19. package/ios/EXLocation.podspec +1 -1
  20. package/package.json +2 -2
  21. package/android/src/main/java/expo/modules/location/LocationActivityResultListener.java +0 -5
  22. package/android/src/main/java/expo/modules/location/LocationHelpers.java +0 -267
  23. package/android/src/main/java/expo/modules/location/LocationModule.java +0 -1012
  24. package/android/src/main/java/expo/modules/location/LocationPackage.java +0 -16
  25. package/android/src/main/java/expo/modules/location/LocationRequestCallbacks.java +0 -12
  26. package/android/src/main/java/expo/modules/location/exceptions/LocationBackgroundUnauthorizedException.java +0 -15
  27. package/android/src/main/java/expo/modules/location/exceptions/LocationRequestRejectedException.java +0 -15
  28. package/android/src/main/java/expo/modules/location/exceptions/LocationSettingsUnsatisfiedException.java +0 -15
  29. package/android/src/main/java/expo/modules/location/exceptions/LocationUnauthorizedException.java +0 -15
  30. package/android/src/main/java/expo/modules/location/exceptions/LocationUnavailableException.java +0 -15
  31. package/android/src/main/java/expo/modules/location/services/LocationTaskService.java +0 -143
  32. package/android/src/main/java/expo/modules/location/taskConsumers/GeofencingTaskConsumer.java +0 -289
  33. package/android/src/main/java/expo/modules/location/taskConsumers/LocationTaskConsumer.java +0 -364
  34. package/unimodule.json +0 -4
package/CHANGELOG.md CHANGED
@@ -10,6 +10,26 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 16.5.1 — 2023-12-19
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
17
+ ## 16.5.0 — 2023-11-14
18
+
19
+ ### 🛠 Breaking changes
20
+
21
+ - Bumped iOS deployment target to 13.4. ([#25063](https://github.com/expo/expo/pull/25063) by [@gabrieldonadel](https://github.com/gabrieldonadel))
22
+ - On `Android` bump `compileSdkVersion` and `targetSdkVersion` to `34`. ([#24708](https://github.com/expo/expo/pull/24708) by [@alanjhughes](https://github.com/alanjhughes))
23
+
24
+ ### 💡 Others
25
+
26
+ - [Android] Moved to the new Modules API. ([#24737](https://github.com/expo/expo/pull/24737) by [@behenate](https://github.com/behenate))
27
+ - Remove `unimodule.json` in favour of `expo-module.config.json`. ([#25100](https://github.com/expo/expo/pull/25100) by [@reichhartd](https://github.com/reichhartd))
28
+
29
+ ### 📚 3rd party library updates
30
+
31
+ - Updated `com.google.android.gms:play-services-location` to `21.0.1`. ([#25028](https://github.com/expo/expo/pull/25028) by [@behenate](https://github.com/behenate))
32
+
13
33
  ## 16.4.0 — 2023-10-17
14
34
 
15
35
  ### 🛠 Breaking changes
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '16.4.0'
6
+ version = '16.5.1'
7
7
 
8
8
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
9
9
  if (expoModulesCorePlugin.exists()) {
@@ -61,11 +61,11 @@ if (!safeExtGet("expoProvidesDefaultConfig", false)) {
61
61
  android {
62
62
  // Remove this if and it's contents, when support for SDK49 is dropped
63
63
  if (!safeExtGet("expoProvidesDefaultConfig", false)) {
64
- compileSdkVersion safeExtGet("compileSdkVersion", 33)
64
+ compileSdkVersion safeExtGet("compileSdkVersion", 34)
65
65
 
66
66
  defaultConfig {
67
67
  minSdkVersion safeExtGet("minSdkVersion", 23)
68
- targetSdkVersion safeExtGet("targetSdkVersion", 33)
68
+ targetSdkVersion safeExtGet("targetSdkVersion", 34)
69
69
  }
70
70
 
71
71
  publishing {
@@ -94,7 +94,7 @@ android {
94
94
  namespace "expo.modules.location"
95
95
  defaultConfig {
96
96
  versionCode 29
97
- versionName "16.4.0"
97
+ versionName "16.5.1"
98
98
  }
99
99
  }
100
100
 
@@ -105,8 +105,7 @@ dependencies {
105
105
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
106
106
  }
107
107
 
108
- api 'com.google.android.gms:play-services-location:20.0.0'
109
-
108
+ api 'com.google.android.gms:play-services-location:21.0.1'
110
109
  api('io.nlopez.smartlocation:library:3.3.3') {
111
110
  transitive = false
112
111
  }
@@ -2,6 +2,7 @@
2
2
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
3
3
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
4
4
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
5
+ <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
5
6
 
6
7
  <application>
7
8
  <service
@@ -0,0 +1,5 @@
1
+ package expo.modules.location
2
+
3
+ interface LocationActivityResultListener {
4
+ fun onResult(resultCode: Int)
5
+ }
@@ -0,0 +1,57 @@
1
+ package expo.modules.location
2
+
3
+ import expo.modules.kotlin.exception.CodedException
4
+
5
+ internal class NoPermissionsModuleException :
6
+ CodedException("Permissions module is null. Are you sure all the installed Expo modules are properly linked?")
7
+
8
+ internal class NoPermissionInManifestException(permissionName: String) :
9
+ CodedException("You need to add `$permissionName` to the AndroidManifest")
10
+
11
+ internal class LocationBackgroundUnauthorizedException :
12
+ CodedException("Not authorized to use background location services")
13
+
14
+ internal class LocationRequestRejectedException(cause: Exception) :
15
+ CodedException("Location request has been rejected: " + cause.message)
16
+
17
+ internal class LocationRequestCancelledException :
18
+ CodedException("Location request has been cancelled")
19
+
20
+ internal class LocationSettingsUnsatisfiedException :
21
+ CodedException("Location request failed due to unsatisfied device settings")
22
+
23
+ internal class LocationUnauthorizedException :
24
+ CodedException("Not authorized to use location services")
25
+
26
+ internal class LocationUnavailableException :
27
+ CodedException("Location is unavailable. Make sure that location services are enabled")
28
+
29
+ internal class LocationUnknownException :
30
+ CodedException("Current location is unknown")
31
+
32
+ internal class SensorManagerUnavailable :
33
+ CodedException("Sensor manager is unavailable")
34
+
35
+ internal class GeocodeException(message: String?, cause: Throwable? = null) :
36
+ CodedException("An exception occurred when accessing the geocode: ${message ?: ""} ${cause?.message ?: ""}")
37
+
38
+ internal class NoGeocodeException :
39
+ CodedException("Could not find the Geocoder")
40
+
41
+ internal class TaskManagerNotFoundException :
42
+ CodedException("Could not find the task manager")
43
+
44
+ internal class GeofencingException(message: String?, cause: Throwable? = null) :
45
+ CodedException("A geofencing exception has occurred: ${message ?: ""} ${cause?.message ?: ""}")
46
+
47
+ internal class MissingActivityManagerException :
48
+ CodedException("Activity manager is unavailable")
49
+
50
+ internal class MissingUIManagerException :
51
+ CodedException("UIManager is unavailable")
52
+
53
+ internal class ConversionException(fromClass: Class<*>, toClass: Class<*>, message: String? = "") :
54
+ CodedException("Couldn't cast from ${fromClass::class.simpleName} to ${toClass::class.java.simpleName}: $message")
55
+
56
+ internal class ForegroundServiceStartNotAllowedException :
57
+ CodedException("Couldn't start the foreground service. Foreground service cannot be started when the application is in the background.")
@@ -0,0 +1,220 @@
1
+ package expo.modules.location
2
+
3
+ import android.content.Context
4
+ import android.location.Location
5
+ import android.location.LocationManager
6
+ import android.os.Bundle
7
+ import com.google.android.gms.location.CurrentLocationRequest
8
+ import com.google.android.gms.location.FusedLocationProviderClient
9
+ import com.google.android.gms.location.Granularity
10
+ import com.google.android.gms.location.LocationRequest
11
+ import com.google.android.gms.location.Priority
12
+ import expo.modules.interfaces.permissions.Permissions
13
+ import expo.modules.kotlin.Promise
14
+ import expo.modules.kotlin.exception.CodedException
15
+ import expo.modules.location.records.LocationLastKnownOptions
16
+ import expo.modules.location.records.LocationOptions
17
+ import expo.modules.location.records.LocationResponse
18
+ import expo.modules.location.records.PermissionRequestResponse
19
+ import io.nlopez.smartlocation.location.config.LocationAccuracy
20
+ import io.nlopez.smartlocation.location.config.LocationParams
21
+ import kotlin.coroutines.resume
22
+ import kotlin.coroutines.resumeWithException
23
+ import kotlin.coroutines.suspendCoroutine
24
+
25
+ class LocationHelpers {
26
+ companion object {
27
+ /**
28
+ * Checks whether given location didn't exceed given `maxAge` and fits in the required accuracy.
29
+ */
30
+ internal fun isLocationValid(location: Location?, options: LocationLastKnownOptions): Boolean {
31
+ if (location == null) {
32
+ return false
33
+ }
34
+ val maxAge = options.maxAge ?: Double.MAX_VALUE
35
+ val requiredAccuracy = options.requiredAccuracy ?: Double.MAX_VALUE
36
+ val timeDiff = (System.currentTimeMillis() - location.time).toDouble()
37
+ return timeDiff <= maxAge && location.accuracy <= requiredAccuracy
38
+ }
39
+
40
+ fun hasNetworkProviderEnabled(context: Context?): Boolean {
41
+ if (context == null) {
42
+ return false
43
+ }
44
+ val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as? LocationManager
45
+ return locationManager != null && locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
46
+ }
47
+
48
+ internal fun prepareLocationRequest(options: LocationOptions): LocationRequest {
49
+ val locationParams = mapOptionsToLocationParams(options)
50
+
51
+ return LocationRequest.Builder(locationParams.interval)
52
+ .setMinUpdateIntervalMillis(locationParams.interval)
53
+ .setMaxUpdateDelayMillis(locationParams.interval)
54
+ .setMinUpdateDistanceMeters(locationParams.distance)
55
+ .setPriority(mapAccuracyToPriority(options.accuracy))
56
+ .build()
57
+ }
58
+
59
+ internal fun prepareCurrentLocationRequest(options: LocationOptions): CurrentLocationRequest {
60
+ val locationParams = mapOptionsToLocationParams(options)
61
+
62
+ return CurrentLocationRequest.Builder().apply {
63
+ setGranularity(Granularity.GRANULARITY_PERMISSION_LEVEL)
64
+ setPriority(mapAccuracyToPriority(options.accuracy))
65
+ setMaxUpdateAgeMillis(locationParams.interval)
66
+ }.build()
67
+ }
68
+
69
+ fun requestSingleLocation(locationProvider: FusedLocationProviderClient, locationRequest: CurrentLocationRequest, promise: Promise) {
70
+ try {
71
+ locationProvider.getCurrentLocation(locationRequest, null)
72
+ .addOnSuccessListener {
73
+ promise.resolve(LocationResponse(it))
74
+ }
75
+ .addOnFailureListener {
76
+ promise.reject(LocationRequestRejectedException(it))
77
+ }
78
+ .addOnCanceledListener {
79
+ promise.reject(LocationRequestCancelledException())
80
+ }
81
+ } catch (e: SecurityException) {
82
+ promise.reject(LocationRequestRejectedException(e))
83
+ }
84
+ }
85
+
86
+ fun requestContinuousUpdates(locationModule: LocationModule, locationRequest: LocationRequest, watchId: Int, promise: Promise) {
87
+ locationModule.requestLocationUpdates(
88
+ locationRequest,
89
+ watchId,
90
+ object : LocationRequestCallbacks {
91
+ override fun onLocationChanged(location: Location) {
92
+ locationModule.sendLocationResponse(watchId, LocationResponse(location))
93
+ }
94
+
95
+ override fun onRequestSuccess() {
96
+ promise.resolve(null)
97
+ }
98
+
99
+ override fun onRequestFailed(cause: CodedException) {
100
+ promise.reject(cause)
101
+ }
102
+ }
103
+ )
104
+ }
105
+
106
+ private fun mapOptionsToLocationParams(options: LocationOptions): LocationParams {
107
+ val accuracy = options.accuracy
108
+ val locationParamsBuilder = buildLocationParamsForAccuracy(accuracy)
109
+
110
+ options.timeInterval?.let {
111
+ locationParamsBuilder.setInterval(it)
112
+ }
113
+ options.distanceInterval?.let {
114
+ locationParamsBuilder.setDistance(it.toFloat())
115
+ }
116
+
117
+ return locationParamsBuilder.build()
118
+ }
119
+
120
+ private fun mapAccuracyToPriority(accuracy: Int): Int {
121
+ return when (accuracy) {
122
+ LocationModule.ACCURACY_BEST_FOR_NAVIGATION, LocationModule.ACCURACY_HIGHEST, LocationModule.ACCURACY_HIGH -> Priority.PRIORITY_HIGH_ACCURACY
123
+ LocationModule.ACCURACY_BALANCED, LocationModule.ACCURACY_LOW -> Priority.PRIORITY_BALANCED_POWER_ACCURACY
124
+ LocationModule.ACCURACY_LOWEST -> Priority.PRIORITY_LOW_POWER
125
+ else -> Priority.PRIORITY_BALANCED_POWER_ACCURACY
126
+ }
127
+ }
128
+
129
+ private fun buildLocationParamsForAccuracy(accuracy: Int): LocationParams.Builder {
130
+ return when (accuracy) {
131
+ LocationModule.ACCURACY_LOWEST -> LocationParams.Builder()
132
+ .setAccuracy(LocationAccuracy.LOWEST)
133
+ .setDistance(3000f)
134
+ .setInterval(10000)
135
+
136
+ LocationModule.ACCURACY_LOW -> LocationParams.Builder()
137
+ .setAccuracy(LocationAccuracy.LOW)
138
+ .setDistance(1000f)
139
+ .setInterval(5000)
140
+
141
+ LocationModule.ACCURACY_BALANCED -> LocationParams.Builder()
142
+ .setAccuracy(LocationAccuracy.MEDIUM)
143
+ .setDistance(100f)
144
+ .setInterval(3000)
145
+
146
+ LocationModule.ACCURACY_HIGH -> LocationParams.Builder()
147
+ .setAccuracy(LocationAccuracy.HIGH)
148
+ .setDistance(50f)
149
+ .setInterval(2000)
150
+
151
+ LocationModule.ACCURACY_HIGHEST -> LocationParams.Builder()
152
+ .setAccuracy(LocationAccuracy.HIGH)
153
+ .setDistance(25f)
154
+ .setInterval(1000)
155
+
156
+ LocationModule.ACCURACY_BEST_FOR_NAVIGATION -> LocationParams.Builder()
157
+ .setAccuracy(LocationAccuracy.HIGH)
158
+ .setDistance(0f)
159
+ .setInterval(500)
160
+
161
+ else -> LocationParams.Builder()
162
+ .setAccuracy(LocationAccuracy.MEDIUM)
163
+ .setDistance(100f)
164
+ .setInterval(3000)
165
+ }
166
+ }
167
+
168
+ fun isAnyProviderAvailable(context: Context?): Boolean {
169
+ val locationManager = context?.getSystemService(Context.LOCATION_SERVICE) as? LocationManager ?: return false
170
+ return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
171
+ }
172
+
173
+ // Decorator for Permissions.getPermissionsWithPermissionsManager, for use in Kotlin coroutines
174
+ internal suspend fun getPermissionsWithPermissionsManager(contextPermissions: Permissions, vararg permissionStrings: String): PermissionRequestResponse {
175
+ return suspendCoroutine { continuation ->
176
+ Permissions.getPermissionsWithPermissionsManager(
177
+ contextPermissions,
178
+ object : Promise {
179
+ override fun resolve(value: Any?) {
180
+ val result = value as? Bundle ?: throw ConversionException(Any::class.java, Bundle::class.java, "value returned by the permission promise is not a Bundle")
181
+ continuation.resume(PermissionRequestResponse(result))
182
+ }
183
+
184
+ override fun reject(code: String, message: String?, cause: Throwable?) {
185
+ continuation.resumeWithException(CodedException(code, message, cause))
186
+ }
187
+ },
188
+ *permissionStrings
189
+ )
190
+ }
191
+ }
192
+
193
+ // Decorator for Permissions.getPermissionsWithPermissionsManager, for use in Kotlin coroutines
194
+ internal suspend fun askForPermissionsWithPermissionsManager(contextPermissions: Permissions, vararg permissionStrings: String): Bundle {
195
+ return suspendCoroutine {
196
+ Permissions.askForPermissionsWithPermissionsManager(
197
+ contextPermissions,
198
+ object : Promise {
199
+ override fun resolve(value: Any?) {
200
+ it.resume(value as? Bundle ?: throw ConversionException(Any::class.java, Bundle::class.java, "value returned by the permission promise is not a Bundle"))
201
+ }
202
+
203
+ override fun reject(code: String, message: String?, cause: Throwable?) {
204
+ it.resumeWithException(CodedException(code, message, cause))
205
+ }
206
+ },
207
+ *permissionStrings
208
+ )
209
+ }
210
+ }
211
+ }
212
+ }
213
+
214
+ /**
215
+ * A singleton that keeps information about whether the app is in the foreground or not.
216
+ * This is a simple solution for passing current foreground information from the LocationModule to LocationTaskConsumer.
217
+ */
218
+ object AppForegroundedSingleton {
219
+ var isForegrounded = false
220
+ }