diff --git a/CHANGELOG.md b/CHANGELOG.md
index bad7ac9..c4e6003 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [2.2.1]
+
+### 2026-06-15
+
+- Fix: Return error when user rejects request to turn on location with `enableLocationManagerFallback=true`. Prior to this fix, it would try to retrieve the location nonetheless and timeout.
+
## [2.2.0]
### 2026-02-02
diff --git a/README.md b/README.md
index cad201c..79247fd 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ In your app-level gradle file, import the `ion-android-geolocation` library like
```
dependencies {
- implementation("io.ionic.libs:iongeolocation-android:2.2.0")
+ implementation("io.ionic.libs:iongeolocation-android:2.2.1")
}
```
diff --git a/build.gradle b/build.gradle
index 66416cb..c0e3f23 100644
--- a/build.gradle
+++ b/build.gradle
@@ -46,8 +46,8 @@ android {
defaultConfig {
minSdk 23
targetSdk 36
- versionCode 3
- versionName "2.2.0"
+ versionCode 4
+ versionName "2.2.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
diff --git a/pom.xml b/pom.xml
index 8d6ca17..f95b78a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,5 +6,5 @@
4.0.0
io.ionic.libs
iongeolocation-android
- 2.2.0
+ 2.2.1
\ No newline at end of file
diff --git a/src/main/kotlin/io/ionic/libs/iongeolocationlib/controller/IONGLOCController.kt b/src/main/kotlin/io/ionic/libs/iongeolocationlib/controller/IONGLOCController.kt
index 9735890..160ed46 100644
--- a/src/main/kotlin/io/ionic/libs/iongeolocationlib/controller/IONGLOCController.kt
+++ b/src/main/kotlin/io/ionic/libs/iongeolocationlib/controller/IONGLOCController.kt
@@ -389,12 +389,13 @@ class IONGLOCController internal constructor(
}
/**
- * @return true if the the settings result is such that the location request must fail
+ * @return true if the settings result is such that the location request must fail
* (even if enableLocationManagerFallback=true), or false otherwise
*/
private fun Result.shouldNotProceed(options: IONGLOCLocationOptions): Boolean =
isFailure && (!options.enableLocationManagerFallback ||
- exceptionOrNull() is IONGLOCException.IONGLOCLocationAndNetworkDisabledException)
+ exceptionOrNull() is IONGLOCException.IONGLOCLocationAndNetworkDisabledException ||
+ exceptionOrNull() is IONGLOCException.IONGLOCRequestDeniedException)
companion object {
private const val LOG_TAG = "IONGeolocationController"
diff --git a/src/main/kotlin/io/ionic/libs/iongeolocationlib/controller/helper/IONGLOCFallbackHelper.kt b/src/main/kotlin/io/ionic/libs/iongeolocationlib/controller/helper/IONGLOCFallbackHelper.kt
index 83f42a0..e54d208 100644
--- a/src/main/kotlin/io/ionic/libs/iongeolocationlib/controller/helper/IONGLOCFallbackHelper.kt
+++ b/src/main/kotlin/io/ionic/libs/iongeolocationlib/controller/helper/IONGLOCFallbackHelper.kt
@@ -31,7 +31,7 @@ internal class IONGLOCFallbackHelper(
*/
@SuppressLint("MissingPermission")
internal suspend fun getCurrentLocation(options: IONGLOCLocationOptions): Location = try {
- withTimeout(options.timeout) {
+ withTimeout(timeMillis = options.timeout) {
suspendCancellableCoroutine { continuation ->
getValidCachedLocation(options)?.let { validCacheLocation ->
continuation.resume(validCacheLocation)
diff --git a/src/test/java/io/ionic/libs/iongeolocationlib/controller/IONGLOCControllerTest.kt b/src/test/java/io/ionic/libs/iongeolocationlib/controller/IONGLOCControllerTest.kt
index 4a92ee0..aa665c0 100644
--- a/src/test/java/io/ionic/libs/iongeolocationlib/controller/IONGLOCControllerTest.kt
+++ b/src/test/java/io/ionic/libs/iongeolocationlib/controller/IONGLOCControllerTest.kt
@@ -231,6 +231,28 @@ class IONGLOCControllerTest {
assertTrue(result.exceptionOrNull() is IONGLOCException.IONGLOCRequestDeniedException)
}
+ @Test
+ fun `given location is off and user does not resolve location settings, when getCurrentLocation is called with enableLocationFallback=True, IONGLOCRequestDeniedException returned`() =
+ runTest {
+ givenSuccessConditions() // to instantiate mocks
+ givenResolvableApiException(Activity.RESULT_CANCELED)
+ // unlike the test above for enableLocationFallback=false
+ // this line is explicitly needed, because otherwise
+ // the SUT would not assume resolving is needed for the fallback
+ // and would try to await a location (which is the bug that gets fixed by
+ // https://github.com/ionic-team/ion-android-geolocation/pull/12)
+ every { LocationManagerCompat.isLocationEnabled(any()) } returns false
+
+ val result = sut.getCurrentPosition(
+ mockk(),
+ locationOptions.copy(enableLocationManagerFallback = true)
+ )
+ testScheduler.advanceTimeBy(DELAY)
+
+ assertTrue(result.isFailure)
+ assertTrue(result.exceptionOrNull() is IONGLOCException.IONGLOCRequestDeniedException)
+ }
+
@Test
fun `given location settings check fails, when getCurrentLocation is called, IONGLOCSettingsException is returned`() =
runTest {
@@ -562,7 +584,12 @@ class IONGLOCControllerTest {
fun `given SETTINGS_CHANGE_UNAVAILABLE error and network+location disabled and enableLocationManagerFallback=true, when getCurrentLocation is called, IONGLOCLocationAndNetworkDisabledException is returned`() =
runTest {
givenSuccessConditions() // to instantiate mocks
- coEvery { locationSettingsTask.await() } throws ApiException(Status(8502, "SETTINGS_CHANGE_UNAVAILABLE"))
+ coEvery { locationSettingsTask.await() } throws ApiException(
+ Status(
+ 8502,
+ "SETTINGS_CHANGE_UNAVAILABLE"
+ )
+ )
every { LocationManagerCompat.isLocationEnabled(any()) } returns false
val result = sut.getCurrentPosition(mockk(), locationOptionsWithFallback)