cordova-diagnostic-plugin
cordova-diagnostic-plugin copied to clipboard
IOS getLocationAuthorizationStatus permissionStatus.GRANTED
Bug report
CHECKLIST
-
[X] I have read the issue reporting guidelines
-
[X] I confirm this is a suspected bug or issue that will affect other users
- [X] I have reproduced the issue using the example project or provided the necessary information to reproduce the issue.
- [X] I have read the documentation thoroughly and it does not help solve my issue.
- [X] I have checked that no similar issues (open or closed) already exist.
Current behavior:
After application deployed and started, I selected the 'Allow while using app' choice as location access on IOS. The getLocationAuthorizationStatus returns permissionStatus.GRANTED, instead of permissionStatus.GRANTED_WHEN_IN_USE. After I change to location mode maualy, the selected value will returns the right value to the getLocationAuthorizationStatus function. But after deploy it is not woking properly.
Expected behavior:
The application should return permissionStatus.GRANTED_WHEN_IN_USE if I select the 'Allow while using app' at first time.
Steps to reproduce:
Screenshots
Environment information
- Cordova CLI version : 10.0.0.
-
cordova -v
-
- Cordova platform version: 6.1.1
-
cordova platform ls
-
- Plugins & versions installed in project (including this plugin)
-
cordova plugin ls
-
- Dev machine OS and version, e.g.
- OSX: IOS 15, IOS 14, macbook IOS simulator
-
sw_vers
-
- Windows 10
-
winver
-
- OSX: IOS 15, IOS 14, macbook IOS simulator
Runtime issue
- Device details
- e.g. iPhone X, Samsung Galaxy S8, iPhone X Simulator, Pixel XL Emulator
- OS details
- e.g. iOS 12.2, Android 9.0
Android build issue:
- Node JS version
-
node -v
-
- Gradle version
-
ls platforms/android/.gradle
-
- Target Android SDK version
-
android:targetSdkVersion
inAndroidManifest.xml
-
- Android SDK details
-
sdkmanager --list | sed -e '/Available Packages/q'
-
iOS build issue:
- Node JS version
-
node -v
14.17.0
-
- XCode version
Related code:
insert any relevant code here such as plugin API calls / input parameters
window.cordova.plugins.diagnostic.getLocationAuthorizationStatus((locationPermission) => {
console.log(`Location permission setting is ${locationPermission}`);
}, (err) => {
console.error('Error', err);
});
Console output Location permission setting is granted
console output
// Paste any relevant JS/native console output here
Other information:
I have not tested this (it is a theory), but with newer iOS versions there might be some magic going on within iOS itself where it has changed the API but tries to stay semi backwards compatible. Meaning that when you initially request cordova.plugins.diagnostic.locationAuthorizationMode.ALWAYS
it will actually ask the user for permission cordova.plugins.diagnostic.locationAuthorizationMode.WHEN_IN_USE
.
Once [...].WHEN_IN_USE
is granted you can request [...].ALWAYS
. But that is not the end because it will ask the user later on or re-request to change in [...].ALWAYS
. Anyway since the API changed I wonder if the behaviour you describe still occurs if you (correctly) request [...].WHEN_IN_USE
instead of [...].ALWAYS
when the app is started/installed initially. Because the actual grant level might be in some limbo state within iOS itself.
cordova.plugins.diagnostic.requestLocationAuthorization(function(status){
console.log(status);
}, function(error){
console.error(error);
}, cordova.plugins.diagnostic.locationAuthorizationMode.WHEN_IN_USE);
This is a quirk of the iOS Location Manager behaviour of iOS 14+
If you request location permission ALWAYS
:
cordova.plugins.diagnostic.requestLocationAuthorization
handleSuggest,
handleError,
cordova.plugins.diagnostic.locationAuthorizationMode.ALWAYS
);
Then select "Allow While Using App" in permission dialog, iOS invokes the locationManagerDidChangeAuthorization delegate method with authorization status kCLAuthorizationStatusAuthorizedAlways.
The plugin then maps this constant to the GRANTED
string value.
Conversely, if you request permission ALWAYS
and you select "Allow Once" in the permission dialog, locationManagerDidChangeAuthorization
will be invoked with authorization status constant kCLAuthorizationStatusAuthorizedWhenInUse which this plugin maps to GRANTED_WHEN_IN_USE
.
For comparison, if you request WHEN_IN_USE
permission and select "Allow Once", locationManagerDidChangeAuthorization
will be invoked with authorization status constant kCLAuthorizationStatusAuthorizedWhenInUse.
And if you request WHEN_IN_USE
permission and select "Allow While Using App", the result is also kCLAuthorizationStatusAuthorizedWhenInUse.
Just to be clear, here are those results in tabular form:
Permission requested | User choice | Native constant | Plugin constant |
---|---|---|---|
ALWAYS | Allow While Using App | kCLAuthorizationStatusAuthorizedAlways |
GRANTED |
ALWAYS | Allow Once | kCLAuthorizationStatusAuthorizedWhenInUse |
GRANTED_WHEN_IN_USE |
WHEN_IN_USE | Allow While Using App | kCLAuthorizationStatusAuthorizedWhenInUse |
GRANTED_WHEN_IN_USE |
WHEN_IN_USE | Allow Once | kCLAuthorizationStatusAuthorizedWhenInUse |
GRANTED_WHEN_IN_USE |
It really does seem like Apple has got this backwards as you'd expect having requested location ALWAYS
that "Allow While Using App" would result in kCLAuthorizationStatusAuthorizedWhenInUse
and Allow Once
would result in kCLAuthorizationStatusAuthorizedAlways
.
I guess the plugin could "remember" that you'd requested ALWAYS
permission and then invert the resulting permission status in locationManagerDidChangeAuthorization
but this would mean the plugin would then not be reflecting the actual native constant being return by the location manager.
Therefore it's probably best that you handle this anomalous behaviour with your own logic at app-level.