Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS] Location update are disabled after one kCLErrorLocationUnknown #244

Open
nbrignol opened this issue Jan 5, 2022 · 6 comments
Open

Comments

@nbrignol
Copy link

nbrignol commented Jan 5, 2022

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

@breautek
Copy link
Contributor

breautek commented Jan 5, 2022

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:

if (error.code != kCLErrorLocationUnknown) {
[self.locationManager stopUpdatingLocation];
__locationStarted = NO;
}

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.

@nbrignol
Copy link
Author

nbrignol commented Jan 5, 2022

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.

@breautek
Copy link
Contributor

breautek commented Jan 5, 2022

Maybe we should pass something special to the error callback or add another specific callback

Is this not already covered via?:

CDVLocationData* lData = self.locationData;
if (lData && __locationStarted) {
// TODO: probably have to once over the various error codes and return one of:
// PositionError.PERMISSION_DENIED = 1;
// PositionError.POSITION_UNAVAILABLE = 2;
// PositionError.TIMEOUT = 3;
NSUInteger positionError = POSITIONUNAVAILABLE;
if (error.code == kCLErrorDenied) {
positionError = PERMISSIONDENIED;
}
[self returnLocationError:positionError withMessage:[error localizedDescription]];
}

or is lData a null pointer for you?

@nbrignol
Copy link
Author

nbrignol commented Jan 6, 2022

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 ?

@katzlbt
Copy link

katzlbt commented Dec 31, 2023

Duplicate of: #224
I think we fixed this issue with denied pull request. You can try. #225

@breautek
Copy link
Contributor

breautek commented Jan 7, 2024

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: #224
I think we fixed this issue with denied pull request. You can try. #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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants