Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0d463d1
fix(ios): implement new timeout logic for getCurrentPosition and watc…
OS-ruimoreiramendes Oct 21, 2025
9c56409
fix(ios): implement new timeout logic for getCurrentPosition and watc…
OS-ruimoreiramendes Oct 21, 2025
c2874c3
fix(ios): implement new timeout logic for getCurrentPosition and watc…
OS-ruimoreiramendes Oct 21, 2025
ed9a106
fix(ios): implement new timeout logic for getCurrentPosition and watc…
OS-ruimoreiramendes Oct 21, 2025
56cdd84
fix(ios): implement new timeout logic for getCurrentPosition and watc…
OS-ruimoreiramendes Oct 21, 2025
8119da9
fix(ios): implement new timeout logic for getCurrentPosition and watc…
OS-ruimoreiramendes Oct 21, 2025
dd25a7d
fix(ios): implement new timeout logic for getCurrentPosition and watc…
OS-ruimoreiramendes Oct 22, 2025
bfbb0a5
fix(ios): implement new timeout logic for getCurrentPosition and watc…
OS-ruimoreiramendes Oct 22, 2025
44e4878
fix(ios): update plugin version 7.1.5-dev.2
OS-ruimoreiramendes Oct 22, 2025
73a11f0
fix(ios): remove empty spaces
OS-ruimoreiramendes Oct 22, 2025
a54221d
fix(ios): update native lib files
OS-ruimoreiramendes Oct 27, 2025
b15174e
fix(ios): update requestSingleLocation and startMonitoringLocation
OS-ruimoreiramendes Oct 27, 2025
dd83b52
fix(ios): added new native lib
OS-ruimoreiramendes Oct 28, 2025
818a8d0
Chore(iOS): update native library IONGeolocationLib to version 2.0.0
OS-ruimoreiramendes Oct 29, 2025
3e8a2ed
fix(ios): resolve conflicts
OS-ruimoreiramendes Oct 29, 2025
52be7a8
chore: clean gradle
OS-ruimoreiramendes Oct 29, 2025
597af24
chore: clean gradle
OS-ruimoreiramendes Oct 29, 2025
e49c797
fix(ios): remove release notes
OS-ruimoreiramendes Oct 29, 2025
0e20bc1
fix(ios): update README file
OS-ruimoreiramendes Oct 30, 2025
e369ccd
fix(ios): add timeout to Constants.Arguments
OS-ruimoreiramendes Oct 30, 2025
e27045b
fix(ios): manage timeout in CallbackManager
OS-ruimoreiramendes Oct 30, 2025
ae1bcf4
fix(ios): version 7.1.5-dev.7
OS-ruimoreiramendes Oct 30, 2025
88902a7
fix(ios): manage timeout in CallbackManager
OS-ruimoreiramendes Oct 30, 2025
2f621fb
fix(ios): added timeout implementation for both getCurrentPosition an…
OS-ruimoreiramendes Oct 30, 2025
b14deb0
fix(ios): remove timeout var
OS-ruimoreiramendes Oct 30, 2025
6f151c5
fix(ios): remove watch callbacks when timeout triggers
OS-ruimoreiramendes Oct 31, 2025
18fff23
fix(ios): remove watch callbacks when timeout triggers
OS-ruimoreiramendes Oct 31, 2025
3583623
fix(ios): fix lock files
OS-ruimoreiramendes Nov 3, 2025
1746507
fix(ios): fix lock files
OS-ruimoreiramendes Nov 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/continuous_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ jobs:
uses: ./.github/actions/setup-tools
- name: 'Prepare example app'
uses: ./.github/actions/prepare-example-app

- name: 'Clean Gradle cache'
run: rm -rf ~/.gradle/caches


- name: 'Build Android example app'
working-directory: ./packages/example-app-capacitor/android
run: ./gradlew clean assembleDebug
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## [Unreleased]


### Chores

- **ios:** update native library IONGeolocationLib to version 2.0.0

# [8.0.0-next.3](https://github.com/ionic-team/capacitor-geolocation/compare/v8.0.0-next.2...v8.0.0-next.3) (2025-10-06)


Expand Down
24 changes: 3 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified packages/.DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/capacitor-plugin/CapacitorGeolocation.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ Pod::Spec.new do |s|
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
s.ios.deployment_target = '15.0'
s.dependency 'Capacitor'
s.dependency 'IONGeolocationLib', spec='1.0.1'
s.dependency 'IONGeolocationLib', spec='2.0.0'
s.swift_version = '5.1'
end
2 changes: 1 addition & 1 deletion packages/capacitor-plugin/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0"),
.package(url: "https://github.com/ionic-team/ion-ios-geolocation.git", from: "1.0.2")
.package(url: "https://github.com/ionic-team/ion-ios-geolocation.git", from: "2.0.0")
],
targets: [
.target(
Expand Down
Copy link
Contributor

@OS-pedrogustavobilro OS-pedrogustavobilro Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When testing I'm observing this behavior in the example app in this repo:

  1. I receive a timeout in watchPosition (right now by setting a timeout of 1ms)
  2. I try a get current position with timeout of 1ms. I receive two timeout errors - I believe 1 for this request and one for watch.
  3. I increase the timeout and call get current position. I start receiving locations in the watch.

All this leads me to believe that perhaps there needs to be logic in place to remove the watch callbacks in case of timeout error? Or to generalize the question: Which GeolocationError's are recoverable for a watch and which are not? I think the code assumes right now that all are, and that's not necessarily the case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, let me take look.
I'll try to replicate it and see if the issue is related to the watch callbacks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With your change now, I'm having this issue: I have a watch in progress, and I trigger a second one (or a get current position) that times out, it also stops receiving updates for the first one.

This and the previous issue are all tied to the fact that timeouts are not specific to one single watch or location request.

Copy link
Contributor Author

@OS-ruimoreiramendes OS-ruimoreiramendes Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve have figured out the cause in onLocationPermissionGranted()

let shouldRequestCurrentPosition = callbackManager?.locationCallbacks.isEmpty == false
let shouldRequestLocationMonitoring = callbackManager?.watchCallbacks.isEmpty == false

When a watch is already active and a getCurrentPosition is triggered, both flags are true. The current position itself doesn’t time out because we return the last known location from the watch.
However, startMonitoringLocation is also called again due to shouldRequestLocationMonitoring being true, which starts a new timer.

This issue existed before the current changes, so it will not be addressed in this PR.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum GeolocationError: Error {
case permissionRestricted
case positionUnavailable
case inputArgumentsIssue(target: GeolocationMethod)
case timeout

func toCodeMessagePair() -> (String, String) {
("OS-PLUG-GLOC-\(String(format: "%04d", code))", description)
Expand All @@ -29,6 +30,7 @@ private extension GeolocationError {
case .watchPosition: 5
case .clearWatch: 6
}
case .timeout: 10
}
}

Expand All @@ -39,6 +41,7 @@ private extension GeolocationError {
case .locationServicesDisabled: "Location services are not enabled."
case .permissionRestricted: "Application's use of location services was restricted."
case .inputArgumentsIssue(let target): "The '\(target.rawValue)' input parameters aren't valid."
case .timeout: "Could not obtain location in time. Try with a higher timeout."
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Capacitor
import IONGeolocationLib
import UIKit

import Combine

@objc(GeolocationPlugin)
Expand All @@ -19,14 +18,16 @@ public class GeolocationPlugin: CAPPlugin, CAPBridgedPlugin {
private var locationService: (any IONGLOCService)?
private var cancellables = Set<AnyCancellable>()
private var locationCancellable: AnyCancellable?
private var timeoutCancellable: AnyCancellable?
private var callbackManager: GeolocationCallbackManager?
private var statusInitialized = false
private var locationInitialized: Bool = false
private var timeout : Int?

override public func load() {
self.locationService = IONGLOCManagerWrapper()
self.callbackManager = .init(capacitorBridge: bridge)

NotificationCenter.default.addObserver(
self,
selector: #selector(appDidBecomeActive),
Expand All @@ -40,8 +41,10 @@ public class GeolocationPlugin: CAPPlugin, CAPBridgedPlugin {
print("App became active. Restarting location monitoring for watch callbacks.")
locationCancellable?.cancel()
locationCancellable = nil
timeoutCancellable?.cancel()
timeoutCancellable = nil
locationInitialized = false

locationService?.stopMonitoringLocation()
locationService?.startMonitoringLocation()
bindLocationPublisher()
Expand All @@ -55,13 +58,15 @@ public class GeolocationPlugin: CAPPlugin, CAPBridgedPlugin {
@objc func getCurrentPosition(_ call: CAPPluginCall) {
shouldSetupBindings()
let enableHighAccuracy = call.getBool(Constants.Arguments.enableHighAccuracy, false)
self.timeout = call.getInt("timeout")
handleLocationRequest(enableHighAccuracy, call: call)
}

@objc func watchPosition(_ call: CAPPluginCall) {
shouldSetupBindings()
let enableHighAccuracy = call.getBool(Constants.Arguments.enableHighAccuracy, false)
let watchUUID = call.callbackId
self.timeout = call.getInt("timeout")
handleLocationRequest(enableHighAccuracy, watchUUID: watchUUID, call: call)
}

Expand All @@ -77,6 +82,8 @@ public class GeolocationPlugin: CAPPlugin, CAPBridgedPlugin {
locationService?.stopMonitoringLocation()
locationCancellable?.cancel()
locationCancellable = nil
timeoutCancellable?.cancel()
timeoutCancellable = nil
locationInitialized = false
}

Expand Down Expand Up @@ -145,7 +152,7 @@ private extension GeolocationPlugin {
locationCancellable = locationService?.currentLocationPublisher
.catch { [weak self] error -> AnyPublisher<IONGLOCPositionModel, Never> in
print("An error was found while retrieving the location: \(error)")

if case IONGLOCLocationError.locationUnavailable = error {
print("Location unavailable (likely due to backgrounding). Keeping watch callbacks alive.")
self?.callbackManager?.sendError(.positionUnavailable)
Expand All @@ -160,6 +167,15 @@ private extension GeolocationPlugin {
.sink(receiveValue: { [weak self] position in
self?.callbackManager?.sendSuccess(with: position)
})

timeoutCancellable = locationService?.locationTimeoutPublisher
.sink(receiveValue: { [weak self] error in
if case .timeout = error {
self?.callbackManager?.sendError(.timeout)
} else {
self?.callbackManager?.sendError(.positionUnavailable)
}
})
}

func requestLocationAuthorisation(type requestType: IONGLOCAuthorisationRequestType) {
Expand Down Expand Up @@ -200,10 +216,10 @@ private extension GeolocationPlugin {
callbackManager?.sendRequestPermissionsSuccess(Constants.AuthorisationStatus.Status.granted)
}
if shouldRequestCurrentPosition {
locationService?.requestSingleLocation()
locationService?.requestSingleLocation(options: IONGLOCRequestOptionsModel(timeout: self.timeout))
}
if shouldRequestLocationMonitoring {
locationService?.startMonitoringLocation()
locationService?.startMonitoringLocation(options: IONGLOCRequestOptionsModel(timeout: self.timeout))
}
}

Expand Down
10 changes: 5 additions & 5 deletions packages/example-app-capacitor/ios/App/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ PODS:
- CapacitorCamera (8.0.0-alpha.1):
- Capacitor
- CapacitorCordova (8.0.0-alpha.2)
- CapacitorGeolocation (8.0.0-next.2):
- CapacitorGeolocation (8.0.0-next.3):
- Capacitor
- IONGeolocationLib (= 1.0.1)
- IONGeolocationLib (= 2.0.0)
- CapacitorSplashScreen (8.0.0-alpha.1):
- Capacitor
- IONGeolocationLib (1.0.1)
- IONGeolocationLib (2.0.0)

DEPENDENCIES:
- "Capacitor (from `../../../../node_modules/.pnpm/@[email protected]_@[email protected]/node_modules/@capacitor/ios`)"
Expand Down Expand Up @@ -38,9 +38,9 @@ SPEC CHECKSUMS:
Capacitor: f88db94b173c6d2c97003248197f749674d42dc8
CapacitorCamera: f072b76519f1a5981becb6caa3ab10c79622ae66
CapacitorCordova: 9b60d7dd7f5035cefe9b5f7f3edf11ccd93b6ae6
CapacitorGeolocation: ed8dbf1b8b4f3bc415c1407333199c383cefa960
CapacitorGeolocation: a7b46178fece0f49a7f856e9a678f02adb40d347
CapacitorSplashScreen: 6a9a07f9b1313faad49dde7bb8f12b7c4fcc3acf
IONGeolocationLib: 20f9d0248a0b5264511fb57a37e25dd2badf797a
IONGeolocationLib: a5e40b54edc2ee9902036eda5aaa41ddf07bb68d

PODFILE CHECKSUM: 4965d688d87bbc9772caec9b620016902fb41d32

Expand Down
Loading
Loading