cordova-plugin-geolocation icon indicating copy to clipboard operation
cordova-plugin-geolocation copied to clipboard

[iOS] Location update are disabled after one kCLErrorLocationUnknown

Open nbrignol opened this issue 3 years ago • 6 comments

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

nbrignol avatar Jan 05 '22 17:01 nbrignol

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.

breautek avatar Jan 05 '22 17:01 breautek

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.

nbrignol avatar Jan 05 '22 17:01 nbrignol

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?

breautek avatar Jan 05 '22 18:01 breautek

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 ?

nbrignol avatar Jan 06 '22 09:01 nbrignol

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

katzlbt avatar Dec 31 '23 01:12 katzlbt

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.

breautek avatar Jan 07 '24 04:01 breautek