Contact Usage permission request iphone - iphone

My app was rejected by the apple review team. According to them the reason is
"17.1: Apps cannot transmit data about a user without obtaining the user's prior permission and providing the user with access to
information about how and where the data will be used.Specifically,
your app accesses the Users contacts with out requesting permission
first"
But, I have used **NSContactsUsageDescription** key in my info.plst to specify the reason of using contacts in my app.
What should I have to do additionally for get permission?

In iOS 6 You Need to use Address-book permission request iphone to access it's Device Contact:-
method of implement code like this example:
ABAddressBookRef addressBook;
if ([self isABAddressBookCreateWithOptionsAvailable]) {
CFErrorRef error = nil;
addressBook = ABAddressBookCreateWithOptions(NULL,&error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
// callback can occur in background, address book must be accessed on thread it was created on
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
} else if (!granted) {
} else {
// access granted
[self GetAddressBook];
}
});
});
} else {
// iOS 4/5
[self GetAddressBook];
}

You have to ask user whether your application can access your Address book. This feature is implemented in iOS 6.0 and above.
You Can try this code Snippet:
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
in - viewWillAppear:
// Asking access of AddressBook
// if in iOS 6
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.0"))
{
// Request authorization to Address Book
addressBook_ = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
ABAddressBookRequestAccessWithCompletion(addressBook_, ^(bool granted, CFErrorRef error)
{
if (granted == NO)
{
// Show an alert for no contact Access
}
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
// The user has previously given access, good to go
}
else
{
// The user has previously denied access
// Send an alert telling user to change privacy setting in settings app
}
}
else // For iOS <= 5
{
// just get the contacts directly
addressBook_ = ABAddressBookCreate();
}

Related

Always return Error FBErrorCategoryUserCancelled while login with facebook in my application

In my Application there are three ways of login. one of them is login with facebook. But when I click on facebook button it ask me for accesing permissions, when click OK then it returs error FBErrorCategoryUserCancelled. And this is not happening on every devices, it happens on some devices. Here is my code -
if ([[FBSession activeSession]isOpen]) {
/*
* if the current session has no publish permission we need to reauthorize
*/
if ([[[FBSession activeSession]permissions]indexOfObject:#"publish_actions"] == NSNotFound) {
[[FBSession activeSession] requestNewPublishPermissions:[NSArray arrayWithObject:#"publish_actions"] defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session,NSError *error){
[ProgressHUD dismiss];
self.view.userInteractionEnabled = YES;
}];
}else{
[self fetchUserDetails];
}
}else{
/*
* open a new session with publish permission
*/
[FBSession openActiveSessionWithPublishPermissions:[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceOnlyMe
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (!error && status == FBSessionStateOpen) {
[self fetchUserDetails];
}else{
NSLog(#"error");
if ([FBErrorUtility shouldNotifyUserForError:error]) {
alertTitle = #"Facebook Error";
alertMessage = [FBErrorUtility userMessageForError:error];
// This code will handle session closures that happen outside of the app
// You can take a look at our error handling guide to know more about it
// https://developers.facebook.com/docs/ios/errors
} else if ([FBErrorUtility errorCategoryForError:error] == FBErrorCategoryAuthenticationReopenSession) {
alertTitle = #"Session Error";
alertMessage = #"Your current session is no longer valid. Please log in again.";
// If the user has cancelled a login, we will do nothing.
// You can also choose to show the user a message if cancelling login will result in
// the user not being able to complete a task they had initiated in your app
// (like accessing FB-stored information or posting to Facebook)
} else if ([FBErrorUtility errorCategoryForError:error] == FBErrorCategoryUserCancelled) {
NSLog(#"user cancelled login");
alertTitle = #"Facebook Error";
alertMessage = #"System login cancelled";
// For simplicity, this sample handles other errors with a generic message
// You can checkout our error handling guide for more detailed information
// https://developers.facebook.com/docs/ios/errors
} else {
alertTitle = #"Something went wrong";
alertMessage = #"Please try again later.";
NSLog(#"Unexpected error:%#", error);
}
[[[UIAlertView alloc] initWithTitle:alertTitle
message:alertMessage
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
[ProgressHUD dismiss];
self.view.userInteractionEnabled = YES;
}
}];
}
Any help will be appreciated.Thank you.
In my case it was because the facebook app's sandbox mode was still on, and therefore result in FBErrorCategoryUserCancelled for anyone who is not an administrator/developer/tester of the app.
To turn off sandbox mode on facebook, go to
https://developers.facebook.com/apps/YOUR_FACEBOOK_APP_ID/review-status/
See where it says "Do you want to make this app and all its live features available to the general public?", make it to be YES. (You might need to insert a contact email before you can access this option).
Or, if you don't want to make the app go public just yet, invite the tester to be an admin/developer/tester of the app. The person need to accept your invitation before he can use it.

Handle addressbook permission from settings-> priacy crashes

I am using the following code to ask the permission from addressbook and save it to app's UserDefaults.
if (ABAddressBookRequestAccessWithCompletion != NULL)
{
// we're on iOS 6
ABAddressBookRef addressBookRef = ABAddressBookCreate();
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
accessgranted = granted;
if(accessgranted)
{
[self saveaddressbookpermission:accessgranted];
[NSThread detachNewThreadSelector:#selector(startbgprocess) toTarget:self withObject:nil];
}
});
CFRelease(addressBookRef);
}
else {
// we're on iOS 5 or older
accessgranted = YES;
[self saveaddressbookpermission:accessgranted];
NSLog(#"in iOS 5");
[NSThread detachNewThreadSelector:#selector(startbgprocess) toTarget:self withObject:nil];
}
The issue is when i try to Reset the privacy settings using Setting->General->Reset -> Reset Location & privacy, but if i try to Change the Privacy Settings from Settings->Privacy-> and switch OFF the permissions from there then my app crashes. How can i handle this situation. Please let me know if any other information required as i am not able to find anything regarding this.

How to ask for permission to access iphone contacts addressbook again?

I am asking permission to access my contacts using the code below.
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized)
{
}
else
{
}
So far everything is working but however if I delete the app and debug again the app wont ask me the permission again. Prior to if I accepted or declined I can see it in privacy contacts and the name of my app whether its ON or OFF.
I want the app to ask me the permission pop up. what should i do
restart the device and reinstall the app. Anyway to clear some sort of
cache?
You can reset your privacy settings.
Settings > General > Reset > Reset Location & Privacy.

Distribution adhoc profile denies access to contacts

My distribution profile does not allow me to access contacts of my iPhone, Do I need to get some special permission from apple? My developer profile works well i.e it can access the contacts of my phone whereas distribution profile denies it. And it is working well in simulator also both in ios 5 simulator as well as iOS 6 simulator.
thanks in advance..
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
NSLog(#"Error ref %#",error);
NSLog(#"Access %i",accessGranted);
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_release(sema);
}
else { // we're on iOS 5 or older
addressBook = ABAddressBookCreate();
accessGranted = YES;
}
if (accessGranted) {
//my code
}

iOS Facebook SDK - Check Permissions

I have a Facebook SSO working perfectly on my app, using last release of Facebook Objective-C SDK.
I need to ask an extra permission inside the app if user do "something". I don't need to ask that permission if user gave it to me before, so, I guess, in Facebook SDK there should be a method
-(BOOL) checkPermission:(NSString*) permission;
so I can use it like this:
if( [facebook checkPermission:#"email"] ) {
Is there a way to do this?
This question is a bit old but you can now check what permissions the active session has without making a graph request. Here is how it's done in the HelloFacebookSample :
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
// permission does not exist
} else {
// permission exists
}
Just replace "publish_actions" with "email".
SDK not providing direct method for checking specific permissions but you can check if user granted permission to your application by checking permissions connection of user object in Graph API
GET https://graph.facebook.com/me/permissions
Same can be achieved with FQL query on permissions table
SELECT email FROM permissions WHERE uid = me()
IMPORTANT: This seems to be true for an older version of the Facebook SDK (for example 3.9.0). In 3.15.0 it doesn't work this way anymore. You should use [session.permissions] as Raphaƫl Agneau says in his answer.
You have to use the following method, because [FBSession activeSession].permissions seems to return the permissions you requested, not the real ones.
[FBRequestConnection startWithGraphPath:#"/me/permissions"
completionHandler:^(FBRequestConnection *c, id result, NSError *error) {
if (!error) {
NSDictionary *permissions= [(NSArray *)[result data] objectAtIndex:0];
if (![permissions objectForKey:#"publish_actions"]) {
// Ok, continue with your logic
} else {
// Permission not found, maybe request it (see below)
}
} else {
// Treat error
}
}];
See here for more info:
https://developers.facebook.com/docs/facebook-login/ios/v2.0#permissions-checking
If the permission is not found you may want to request it this way:
[session requestNewPublishPermissions:PERMISSIONS_YOU_WANT
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession* session, NSError* error) {
// Try again the /me/permissions above
}];
Here's my code for FBSDK 4.2.0 for checking permissions. The string that's passed in is the name of the permission, e.g. "publish_actions"
- (void) checkForPermission:(NSString *)permission granted:(void (^)(void))sBlock denied:(void (^)(void))fBlock {
if ([FBSDKAccessToken currentAccessToken]) {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me/permissions" parameters:nil] startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
BOOL hasPermission = NO;
if (!error) {
NSArray *permissions = [result objectForKey:#"data"];
for (NSDictionary *dict in permissions) {
if ([[dict objectForKey:#"permission"] isEqualToString:permission]) {
if ([[dict objectForKey:#"status"] isEqualToString:#"granted"]) {
hasPermission = YES;
}
}
}
}
if (hasPermission) {
(sBlock) ? sBlock() : sBlock;
} else {
(fBlock) ? fBlock() : fBlock;
}
}];
} else {
(fBlock) ? fBlock() : fBlock;
}
}
For the SDK 4+ you have these 2 ways of getting the permissions:
[[FBSDKAccessToken currentAccessToken] hasGranted:#"user_photos"]
or
[[[FBSDKAccessToken currentAccessToken] permissions] containsObject:#"user_photos"]