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();
}
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.
I've been trying for the past two days to connect to multiple accounts for my app, without success.
I've read that there was potentially a problem with Facebook SDK not clearing the cached token correctly. I am using version 3.1.1.
Here is how it goes.
From fresh install:
Connect to account 1.
Launch game and login successfully. Everything is fine.
Close the game
Goto settings and change to account 2.
Launch game, login failed.
I Am receiving that error code from openActiveSessionWithReadPermissions : FBSessionStateClosedLoginFailed
And even if I press the OK button when Facebook is asking for my permission to access my info, the granted variable that comes back says NO.
The research I did brought me multiple solutions that failed, unfortunately.
I tried resynchronizing with this function:
- (void)fbResync
{
ACAccountStore *accountStore;
ACAccountType *accountTypeFB;
if ((accountStore = [[ACAccountStore alloc] init]) && (accountTypeFB = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook] ) )
{
NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
id account;
if (fbAccounts && [fbAccounts count] > 0 && (account = [fbAccounts objectAtIndex:0]))
{
[accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error)
{
//we don't actually need to inspect renewResult or error.
if (error){
}
}];
}
}
fbAccounts always return me an empty array. So I cannot really resynchronize.
I also tried to clear facebook token in my status switch
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
{
[FBSession.activeSession close];
[FBSession.activeSession closeAndClearTokenInformation];
// Clear out the Facebook instance
[self.facebook logout];
self.facebook.accessToken = nil;
self.facebook.expirationDate = nil
}break;
No matter what I do, It seems that I cannot completely get rid of my facebook token.
The only way I found was to reset the settings of the IPAD which is not a solution.
Does anybody have more options I could try?
Thanks!
Tickets I'm aware of :
Facebook authorization fails on iOS6 when switching FB account on device
Facebook SDK 3.1 - Error validating access token
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
}
I'm trying to perform a simple posting procedure:
- (IBAction)directPostClick:(id)sender {
self.statusLabel.text = #"Waiting for authorization...";
if (self.accountStore == nil) {
self.accountStore = [[ACAccountStore alloc] init];
}
ACAccountType * facebookAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSArray * permissions = #[#"publish_stream", #"user_checkins", #"publish_checkins", #"user_likes", #"user_videos"];
NSDictionary * dict = #{ACFacebookAppIdKey : #"My app id here", ACFacebookPermissionsKey : permissions, ACFacebookAudienceKey : ACFacebookAudienceOnlyMe};
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
__block NSString * statusText = nil;
if (granted) {
statusText = #"Logged in";
NSArray * accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
self.facebookAccount = [accounts lastObject];
NSLog(#"account is: %#", self.facebookAccount);
self.statusLabel.text = statusText;
[self postToFeed];
}
else {
self.statusLabel.text = #"Login failed";
NSLog(#"error is: %#", error);
}
}];
}
EDITED:
The problem is that when I click on alertView's OK button (don't allow doesn't work either) nothing happens! - This behavoir now changed with this
iOS 6 Facebook posting procedure ends up with "remote_app_id does not match stored id" So instead of just "nothing happens" I've got an error
"The Facebook server could not fulfill this access request: remote_app_id does not match stored id"
So , it seems that alert view's click handler doing nothing, my completionHandler is never called.
I do have the similar problem already: iOS 6 Social integration - go to settings issue
And I think that it is the same problem here. What do you guys think about it?
P.S.
I'm running on MAC mini, OS X 10.8.1 with latest xcode 4.5 (4G182) and using iPhone 6.0 simulator.
ADDED:
By the Bjorn's request adding the postToFeed method although it is never called:
- (void)postToFeed {
NSDictionary * parameters = #{#"message" : #"Hello world!"};
NSURL * feedUrl = [NSURL URLWithString:#"https://graph.facebook.com/me/feed"];
SLRequest * request = [SLRequest requestForServiceType:SLServiceTypeFacebook requestMethod:SLRequestMethodPOST URL:feedUrl parameters:parameters];
request.account = self.facebookAccount;
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
self.statusLabel.text = #"Posted!";
});
}];
}
I also experienced some difficulties when working with the Accounts Framework and the Facebook integration. Here is what I've learned and how I got it working.
1. Make sure you've setup your App on Facebook correctly
You need to set how your App integrates with Facebook to Native iOS App and enter the Bundle ID of your App into the designated field. (Edit: Note that bundle IDs are case sensitive) You can set the iTunes ID to 0 for now. Enable Facebook Login and set the App Type in the advanced settings tab to Native/Desktop.
Also set App Secret in Client to No.
If one or more of these options are not set correctly it's very likely you get the error The Facebook server could not fulfill this access request: remote_app_id does not match stored id.
(Edit: You also have to ensure the sandbox is disabled.)
2. Installing the Facebook App for the first time
When first installing an App via the native Facebook integration on iOS (and Mac OS X too), you must ask for a basic read permission only! Nothing else as email, user_birthday and user_location is allowed here. Using user_about_me, which is also a basic read permission according to the Facebook documentation, does not work. This is pretty confusing if you previously worked with the Facebook JavaScript SDK or the Facebook PHP SDK, because it asks for the basic permissions by default without you having to do something. Facebook also updated their documentation with a short step-by-step guide on how to use the new Facebook SDK on iOS 6.
3. Requesting additional permissions
It's important to know, that you may not ask for read and write permissions at the same time. That's also something experienced Facebook SDK developers may find confusing. Requesting the read_stream permission along with the publish_stream permission will make the request fail, resulting in the error An app may not aks for read and write permissions at the same time.
As Facebook does not really distinguish between read/write permissions in the Permission Reference, you must identify write permissions by yourself. They're usually prefixed with manage_*, publish_*, create_* or suffixed by *_management.
Facebook does also not recommend to ask for additional permissions immediately after getting basic permissions. The documentation says "You are now required to request read and publish permission separately (and in that order). Most likely, you will request the read permissions for personalization when the app starts and the user first logs in. Later, if appropriate, your app can request publish permissions when it intends to post data to Facebook. [...] Asking for the two types separately also greatly improves the chances that users will grant the publish permissions, since your app will only seek them at the time it needs them, most likely when the user has a stronger intent.".
4. Sample Code
The following sample code should work on iOS and Mac OS X:
ACAccountType * facebookAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
// At first, we only ask for the basic read permission
NSArray * permissions = #[#"email"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"My app id here", ACFacebookAppIdKey, permissions, ACFacebookPermissionsKey, ACFacebookAudienceOnlyMe, ACFacebookAudienceKey, nil];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
/**
* The user granted us the basic read permission.
* Now we can ask for more permissions
**/
NSArray *readPermissions = #[#"read_stream", #"read_friendlists"];
[dict setObject:readPermissions forKey: ACFacebookPermissionsKey];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if(granted && error == nil) {
/**
* We now should have some read permission
* Now we may ask for write permissions or
* do something else.
**/
} else {
NSLog(#"error is: %#",[error description]);
}
}];
} else {
NSLog(#"error is: %#",[error description]);
}
}];
make sure sandbox mode is not activated if you are trying to access facebook account from application for non developer users.