[TIMOB-20004] iOS: Differences between new permission request responses
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Medium |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2015-12-29T10:34:35.000+0000 |
Affected Version/s | Release 5.1.0 |
Fix Version/s | Release 5.2.0 |
Components | iOS |
Labels | notable |
Reporter | Fokke Zandbergen |
Assignee | Srikanth Sombhatla |
Created | 2015-11-17T14:24:13.000+0000 |
Updated | 2016-02-10T00:52:02.000+0000 |
Description
While working in the [5.1 sample](https://github.com/appcelerator-developer-relations/appc-sample-ti510) I noticed some differences between the responses of the new permission request methods. I created a separate test case to show the differences so we can address them in a next release. Nothing big, except for the first bullet maybe.
* Unlike the others, the callback for
requestLocationPermissions()
is only called the first time. You have to force close and then re-open the app for it to work again.
* The response for requestLocationPermissions
also has authorizationStatus
, which would be very useful to have in the response for the others as well.
* On success, the response for requestLocationPermissions
has an empty string for error
where it should either have a message or be undefined.
* When unknown, requestContactsPermissions
has a not very helpful _Access Denied_ error
instead of just being undefined like Calendar
and Camera
.
* Unless permission was granted, the error
for requestLocationPermissions
is always _The user is unable to allow access to location._, which is not very helpful or even misleading since the user is perfectly able, he just denied permission to the app. Calendar and Contacts have better error messages.
* When denied, the response for requestCameraPermissions
has no error
like the others.
* I have no idea where code
comes from but if I deny it (probably by coincidence) correctly maps to AUTHORIZATION_DENIED
for Calendar and Contacts. Would be helpful to have the meaning of this code documented.
* In iOS 8, denying contacts permission sends success response to callback.
Sample
Don't forget to add<key>NSLocationAlwaysUsageDescription</key><string>Deny or grant permission to test different scenarios.</string>
to tiapp.xml
.
var win = Ti.UI.createWindow({
backgroundColor: 'white'
});
var btn = Ti.UI.createButton({
title: 'Request Permissions'
});
btn.addEventListener('click', function(e) {
console.log('\n--------------------------------------------------------\n');
var Calendar = {};
Calendar[Ti.Calendar.AUTHORIZATION_AUTHORIZED] = 'AUTHORIZATION_AUTHORIZED';
Calendar[Ti.Calendar.AUTHORIZATION_DENIED] = 'AUTHORIZATION_DENIED';
Calendar[Ti.Calendar.AUTHORIZATION_RESTRICTED] = 'AUTHORIZATION_RESTRICTED';
Calendar[Ti.Calendar.AUTHORIZATION_UNKNOWN] = 'AUTHORIZATION_UNKNOWN';
console.log('Ti.Calendar.hasCalendarPermissions ' + Ti.Calendar.hasCalendarPermissions());
console.log('Ti.Calendar.eventsAuthorization Ti.Calendar.' + Calendar[Ti.Calendar.eventsAuthorization] + '\n');
var Contacts = {};
Contacts[Ti.Contacts.AUTHORIZATION_AUTHORIZED] = 'AUTHORIZATION_AUTHORIZED';
Contacts[Ti.Contacts.AUTHORIZATION_DENIED] = 'AUTHORIZATION_DENIED';
Contacts[Ti.Contacts.AUTHORIZATION_RESTRICTED] = 'AUTHORIZATION_RESTRICTED';
Contacts[Ti.Contacts.AUTHORIZATION_UNKNOWN] = 'AUTHORIZATION_UNKNOWN';
console.log('Ti.Contacts.hasContactsPermissions ' + Ti.Contacts.hasContactsPermissions());
console.log('Ti.Contacts.contactsAuthorization Ti.Contacts.' + Contacts[Ti.Contacts.contactsAuthorization] + '\n');
var Geolocation = {};
Geolocation[Ti.Geolocation.AUTHORIZATION_AUTHORIZED] = 'AUTHORIZATION_AUTHORIZED';
Geolocation[Ti.Geolocation.AUTHORIZATION_DENIED] = 'AUTHORIZATION_DENIED';
Geolocation[Ti.Geolocation.AUTHORIZATION_RESTRICTED] = 'AUTHORIZATION_RESTRICTED';
Geolocation[Ti.Geolocation.AUTHORIZATION_UNKNOWN] = 'AUTHORIZATION_UNKNOWN';
Geolocation[Ti.Geolocation.AUTHORIZATION_ALWAYS] = 'AUTHORIZATION_ALWAYS';
Geolocation[Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE] = 'AUTHORIZATION_WHEN_IN_USE';
console.log('Ti.Geolocation.hasLocationPermissions ' + Ti.Geolocation.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_ALWAYS));
console.log('Ti.Geolocation.locationServicesAuthorization Ti.Geolocation.' + Geolocation[Ti.Geolocation.locationServicesAuthorization] + '\n');
var Media = {};
Media[Ti.Media.CAMERA_AUTHORIZATION_AUTHORIZED] = 'CAMERA_AUTHORIZATION_AUTHORIZED';
Media[Ti.Media.CAMERA_AUTHORIZATION_DENIED] = 'CAMERA_AUTHORIZATION_DENIED';
Media[Ti.Media.CAMERA_AUTHORIZATION_RESTRICTED] = 'CAMERA_AUTHORIZATION_RESTRICTED';
Media[Ti.Media.CAMERA_AUTHORIZATION_NOT_DETERMINED] = 'CAMERA_AUTHORIZATION_NOT_DETERMINED';
console.log('Ti.Media.hasCameraPermissions ' + Ti.Media.hasCameraPermissions());
console.log('Ti.Media.cameraAuthorizationStatus Ti.Media.' + Media[Ti.Media.cameraAuthorizationStatus] + '\n');
console.log('--------------------------------------------------------\n');
Ti.Calendar.requestCalendarPermissions(function(e) {
console.log('Ti.Calendar.requestCalendarPermissions ' + JSON.stringify(e, null, 2));
console.log('Ti.Calendar.requestCalendarPermissions:code (mapped) ' + Calendar[e.code] + '\n');
});
Ti.Contacts.requestContactsPermissions(function(e) {
console.log('Ti.Contacts.requestContactsPermissions ' + JSON.stringify(e, null, 2));
console.log('Ti.Contacts.requestContactsPermissions:code (mapped) ' + Contacts[e.code] + '\n');
});
Ti.Geolocation.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_ALWAYS, function(e) {
console.log('Ti.Geolocation.requestLocationPermissions ' + JSON.stringify(e, null, 2));
console.log('Ti.Geolocation.requestLocationPermissions:code (mapped) ' + Geolocation[e.code]);
console.log('Ti.Geolocation.requestLocationPermissions:authorizationStatus ' + Geolocation[e.authorizationStatus] + '\n');
});
Ti.Media.requestCameraPermissions(function(e) {
console.log('Ti.Media.requestCameraPermissions ' + JSON.stringify(e, null, 2));
console.log('Ti.Media.requestCameraPermissions:code (mapped) ' + Media[e.code] + '\n');
});
});
win.add(btn);
win.open();
Logs
Scenario: Deny All
[INFO] Ti.Calendar.hasCalendarPermissions false
[INFO] Ti.Calendar.eventsAuthorization Ti.Calendar.AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Contacts.hasContactsPermissions false
[INFO] Ti.Contacts.contactsAuthorization Ti.Contacts.AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Geolocation.hasLocationPermissions false
[INFO] Ti.Geolocation.locationServicesAuthorization Ti.Geolocation.AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Media.hasCameraPermissions false
[INFO] Ti.Media.cameraAuthorizationStatus Ti.Media.CAMERA_AUTHORIZATION_NOT_DETERMINED
[INFO]
[INFO] Ti.Calendar.requestCalendarPermissions {
[INFO] "success": false,
[INFO] "code": 1
[INFO] }
[INFO] Ti.Calendar.requestCalendarPermissions:code (mapped) AUTHORIZATION_RESTRICTED
[INFO]
[INFO] Ti.Contacts.requestContactsPermissions {
[INFO] "success": false,
[INFO] "error": "Access Denied",
[INFO] "code": 100
[INFO] }
[INFO] Ti.Contacts.requestContactsPermissions:code (mapped) undefined
[INFO]
[INFO] Ti.Media.requestCameraPermissions {
[INFO] "success": false,
[INFO] "code": 1
[INFO] }
[INFO] Ti.Media.requestCameraPermissions:code (mapped) CAMERA_AUTHORIZATION_RESTRICTED
Because of TIMOB-20002 I use the Ti 5.1 Sample App to read the Geolocation callback:
[INFO] Ti.Geolocation.requestLocationPermissions {
[INFO] "success": false,
[INFO] "code": 1,
[INFO] "authorizationStatus": 2,
[INFO] "error": "The user is unable to allow access to location."
[INFO] }
[INFO] Ti.Geolocation.requestLocationPermissions.code (mapped) Ti.Geolocation.AUTHORIZATION_RESTRICTED
[INFO] Ti.Geolocation.requestLocationPermissions.authorizationStatus (mapped) Ti.Geolocation.AUTHORIZATION_DENIED
Scenario: Denied Before
[INFO] Ti.Calendar.hasCalendarPermissions false
[INFO] Ti.Calendar.eventsAuthorization Ti.Calendar.AUTHORIZATION_DENIED
[INFO]
[INFO] Ti.Contacts.hasContactsPermissions false
[INFO] Ti.Contacts.contactsAuthorization Ti.Contacts.AUTHORIZATION_DENIED
[INFO]
[INFO] Ti.Geolocation.hasLocationPermissions false
[INFO] Ti.Geolocation.locationServicesAuthorization Ti.Geolocation.AUTHORIZATION_DENIED
[INFO]
[INFO] Ti.Media.hasCameraPermissions false
[INFO] Ti.Media.cameraAuthorizationStatus Ti.Media.CAMERA_AUTHORIZATION_DENIED
[INFO]
[INFO] --------------------------------------------------------
[INFO]
[INFO] Ti.Calendar.requestCalendarPermissions {
[INFO] "success": false,
[INFO] "error": "The user has denied access to events in Calendar.",
[INFO] "code": 2
[INFO] }
[INFO] Ti.Calendar.requestCalendarPermissions:code (mapped) AUTHORIZATION_DENIED
[INFO]
[INFO] Ti.Contacts.requestContactsPermissions {
[INFO] "success": false,
[INFO] "error": "The user has denied access to the address book",
[INFO] "code": 2
[INFO] }
[INFO] Ti.Contacts.requestContactsPermissions:code (mapped) AUTHORIZATION_DENIED
[INFO]
[INFO] Ti.Media.requestCameraPermissions {
[INFO] "success": false,
[INFO] "code": 1
[INFO] }
[INFO] Ti.Media.requestCameraPermissions:code (mapped) CAMERA_AUTHORIZATION_RESTRICTED
Because of TIMOB-20002 I use the Ti 5.1 Sample App to read the Geolocation callback:
[INFO] Ti.Geolocation.requestLocationPermissions {
[INFO] "success": false,
[INFO] "code": 1,
[INFO] "authorizationStatus": 2,
[INFO] "error": "The user is unable to allow access to location."
[INFO] }
[INFO] Ti.Geolocation.requestLocationPermissions.code (mapped) Ti.Geolocation.AUTHORIZATION_RESTRICTED
[INFO] Ti.Geolocation.requestLocationPermissions.authorizationStatus (mapped) Ti.Geolocation.AUTHORIZATION_DENIED
Scenario: Allow All
[INFO] Ti.Calendar.hasCalendarPermissions false
[INFO] Ti.Calendar.eventsAuthorization Ti.Calendar.AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Contacts.hasContactsPermissions false
[INFO] Ti.Contacts.contactsAuthorization Ti.Contacts.AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Geolocation.hasLocationPermissions false
[INFO] Ti.Geolocation.locationServicesAuthorization Ti.Geolocation.AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Media.hasCameraPermissions false
[INFO] Ti.Media.cameraAuthorizationStatus Ti.Media.CAMERA_AUTHORIZATION_NOT_DETERMINED
[INFO]
[INFO] --------------------------------------------------------
[INFO]
[INFO] Ti.Calendar.requestCalendarPermissions {
[INFO] "success": true,
[INFO] "code": 0
[INFO] }
[INFO] Ti.Calendar.requestCalendarPermissions:code (mapped) AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Contacts.requestContactsPermissions {
[INFO] "success": true,
[INFO] "code": 0
[INFO] }
[INFO] Ti.Contacts.requestContactsPermissions:code (mapped) AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Media.requestCameraPermissions {
[INFO] "success": true,
[INFO] "code": 0
[INFO] }
[INFO] Ti.Media.requestCameraPermissions:code (mapped) CAMERA_AUTHORIZATION_NOT_DETERMINED
Because of TIMOB-20002 I use the Ti 5.1 Sample App to read the Geolocation callback:
[INFO] Ti.Geolocation.requestLocationPermissions {
[INFO] "success": true,
[INFO] "code": 0,
[INFO] "authorizationStatus": 3,
[INFO] "error": ""
[INFO] }
[INFO] Ti.Geolocation.requestLocationPermissions.code (mapped) Ti.Geolocation.AUTHORIZATION_UNKNOWN
[INFO] Ti.Geolocation.requestLocationPermissions.authorizationStatus (mapped) Ti.Geolocation.AUTHORIZATION_AUTHORIZED
Scenario: Allowed All Before
[INFO] Ti.Calendar.hasCalendarPermissions true
[INFO] Ti.Calendar.eventsAuthorization Ti.Calendar.AUTHORIZATION_AUTHORIZED
[INFO]
[INFO] Ti.Contacts.hasContactsPermissions true
[INFO] Ti.Contacts.contactsAuthorization Ti.Contacts.AUTHORIZATION_AUTHORIZED
[INFO]
[INFO] Ti.Geolocation.hasLocationPermissions true
[INFO] Ti.Geolocation.locationServicesAuthorization Ti.Geolocation.AUTHORIZATION_ALWAYS
[INFO]
[INFO] Ti.Media.hasCameraPermissions true
[INFO] Ti.Media.cameraAuthorizationStatus Ti.Media.CAMERA_AUTHORIZATION_AUTHORIZED
[INFO]
[INFO] --------------------------------------------------------
[INFO]
[INFO] Ti.Calendar.requestCalendarPermissions {
[INFO] "success": true,
[INFO] "code": 0
[INFO] }
[INFO] Ti.Calendar.requestCalendarPermissions:code (mapped) AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Contacts.requestContactsPermissions {
[INFO] "success": true,
[INFO] "code": 0
[INFO] }
[INFO] Ti.Contacts.requestContactsPermissions:code (mapped) AUTHORIZATION_UNKNOWN
[INFO]
[INFO] Ti.Media.requestCameraPermissions {
[INFO] "success": true,
[INFO] "code": 0
[INFO] }
[INFO] Ti.Media.requestCameraPermissions:code (mapped) CAMERA_AUTHORIZATION_NOT_DETERMINED
Because of TIMOB-20002 I use the Ti 5.1 Sample App to read the Geolocation callback:
[INFO] Ti.Geolocation.requestLocationPermissions {
[INFO] "success": true,
[INFO] "code": 0,
[INFO] "authorizationStatus": 3,
[INFO] "error": ""
[INFO] }
[INFO] Ti.Geolocation.requestLocationPermissions.code (mapped) Ti.Geolocation.AUTHORIZATION_UNKNOWN
[INFO] Ti.Geolocation.requestLocationPermissions.authorizationStatus (mapped) Ti.Geolocation.AUTHORIZATION_AUTHORIZED
PR: https://github.com/appcelerator/titanium_mobile/pull/7528 See my comments for each bullet item: *Unlike the others, the callback for requestLocationPermissions() is only called the first time. You have to force close and then re-open the app for it to work again.* Already fixed in TIMOB-20002 *The response for requestLocationPermissions also has authorizationStatus, which would be very useful to have in the response for the others as well.* This needs to get in parity with Android. Will investigate and do as a separate ticket TIMOB-20084 *On success, the response for requestLocationPermissions has an empty string for error where it should either have a message or be undefined.* Sriks: Already fixed in TIMOB-20002 *When unknown, requestContactsPermissions has a not very helpful Access Denied error instead of just being undefined like Calendar and Camera.* Fixed in this ticket. Changed to a message similar to other permissions: "The user has denied access to the address book" *Unless permission was granted, the error for requestLocationPermissions is always The user is unable to allow access to location., which is not very helpful or even misleading since the user is perfectly able, he just denied permission to the app. Calendar and Contacts have better error messages.* Already fixed in TIMOB-20002 *When denied, the response for requestCameraPermissions has no error like the others.* Fixed in this ticket. Same is fixed for Calendar. *I have no idea where code comes from but if I deny it (probably by coincidence) correctly maps to AUTHORIZATION_DENIED for Calendar and Contacts. Would be helpful to have the meaning of this code documented.* Yes it is coincidence! code in iOS is framework specific. But the docs says 0 is for success and any non zero is for failure. I will create a separate ticket for this since each framework returns a different code and not in parity with Android.
Awesome work [~ssombhatla]. It's the details that make a great product!
Reviewed , there were some issues with TIMOB-20002, however I've left a comment there and 2 new PRs. Everything else looks good. Thanks [~ssombhatla]!
Not sure why this was resolved without a PR being merged. Please address comments in https://github.com/appcelerator/titanium_mobile/pull/7528
[~ssombhatla] PR on master merged, please provide a backport for 5_2_X to make this change available in 5.2.0.
[~hansknoechel] 5_2_X backport PR https://github.com/appcelerator/titanium_mobile/pull/7603
Backport merged, resolving ticket!
Verified fixed, using: MacOS 10.11.3 (15D21) Studio 4.5.0.201602050824 Ti SDK 5.2.0.v20160208101502 Appc NPM 4.2.3-2 Appc CLI 5.2.0-249 Alloy 1.7.33 Xcode 7.2 (7C68) As stated by Srikanth, many issues from this ticket are addressed elsewhere. Tested with the sample code provided. All proper messages were displayed with allowing or denying permissions. Permissions now are accessed and display similar messaging.