cordova-plugin-geolocation
cordova-plugin-geolocation copied to clipboard
[iOS] Location update are disabled after one kCLErrorLocationUnknown
Bug Report
Problem
On iOS, start requesting location updates. You reveive locations updates. Ok. Put the app in background and make the phone in sleep mode (press the right button). The app receive still some updates then an error is triggered. That is normal.
What is expected to happen?
When I wake up the phone and the app in foreground, I expect to be notified again with locations updates.
What does actually happen?
When you restart the app, no more updates. In the error delegate, the plugin call "stopUpdatingLocation". I think there is no reason to do that.
Information
Command or Code
In locationManager:didFailWithError:
This code should be removed
if (error.code != kCLErrorLocationUnknown) { [self.locationManager stopUpdatingLocation]; __locationStarted = NO; }
Environment, Platform, Device
Tested on iPhone 13 mini iOS 15.1.1
In the error delegate, the plugin call "stopUpdatingLocation". I think there is no reason to do that.
I think this is intentional based on Apple's guidelines on handling location errors.
If the user denies your app's use of the location service, this method reports a kCLErrorDenied error. Upon receiving such an error, you should stop the location service.
The code:
https://github.com/apache/cordova-plugin-geolocation/blob/5957a80f644ac1d8477e501e99f7fa04f64b9a3d/src/ios/CDVLocation.m#L349-L352
follows this suggestion (although a bit too broadly) by stopping the service if the error is not an kCLErrorLocationUnknown
error. The reason for this "not kCLErrorLocationUnknown" check is because kCLErrorLocationUnknown
can safely be ignored.
I suspect that you're not receiving kCLErrorLocationUnknown
here and when the app goes into the background, you're actualyl receiving a different error, likely kCLErrorDenied because you require special permissions for background location access.
Yes ok, that is a kCLErrorDenied. The problem is the JS side is not notified in this very case (the request has been stoped because background). Maybe we should pass something special to the error callback or add another specific callback (locationRequestStopped?).
Thank you.
Maybe we should pass something special to the error callback or add another specific callback
Is this not already covered via?:
https://github.com/apache/cordova-plugin-geolocation/blob/5957a80f644ac1d8477e501e99f7fa04f64b9a3d/src/ios/CDVLocation.m#L336-L347
or is lData
a null pointer for you?
No, lData is not null so the error callback seems to be called with PERMISSIONDENIED (=1).
But still it's hard to find out ... I guess we need
- at least to document that (ios quirk : when you receive an error=1, the location service is stopped by the plugin so you should restart it when needed)
- or you let the responsability to stop the service in the JS side (and document it : ios quirk : when you receive an error=1 the apple guideline ask you to stop the service)
- or add another callback "locationServiceStopped" to simplify the handling of the restart.
What do you think ?
Duplicate of: https://github.com/apache/cordova-plugin-geolocation/issues/224 I think we fixed this issue with denied pull request. You can try. https://github.com/apache/cordova-plugin-geolocation/pull/225
No, lData is not null so the error callback seems to be called with PERMISSIONDENIED (=1).
But still it's hard to find out ... I guess we need
- at least to document that (ios quirk : when you receive an error=1, the location service is stopped by the plugin so you should restart it when needed)
- or you let the responsability to stop the service in the JS side (and document it : ios quirk : when you receive an error=1 the apple guideline ask you to stop the service)
- or add another callback "locationServiceStopped" to simplify the handling of the restart.
What do you think ?
Based on https://developer.apple.com/documentation/corelocation/cllocationmanagerdelegate/1423786-locationmanager?language=objc
The location manager calls this method when it encounters an error trying to get the location or heading data. If the location service is unable to retrieve a location right away, it reports a kCLErrorLocationUnknown error and keeps trying. In such a situation, you can simply ignore the error and wait for a new event. If a heading could not be determined because of strong interference from nearby magnetic fields, this method returns kCLErrorHeadingFailure.
If the user denies your app's use of the location service, this method reports a kCLErrorDenied error. Upon receiving such an error, you should stop the location service.
I think perhaps we can proceed... If we are stopping location services on kCLErrorLocationUnknown
, then perhaps that logic can be removed, as the apple docs states it can be ignored. I think we'd need to pay attention to make sure any configured timeouts are properly honoured.
Duplicate of: https://github.com/apache/cordova-plugin-geolocation/issues/224 I think we fixed this issue with denied pull request. You can try. https://github.com/apache/cordova-plugin-geolocation/pull/225
I don't think this is a duplicate because #224 is subjected around kCLErrorDenied
and Apple explicitly states that the application should stop location services on this error code, so I believe the geolocation plugin behaviour in this case is intentional. This issue is in regards of kCLErrorLocationUnknown
.
In either case, listening on the resume
event and calling watchPosition
again should be a sufficient workaround.