I am attempting to add facebook integration into a project. In iOS 6+, I request access to the user's facebook accounts with the following code.
if (self.accountStore == nil) self.accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountTypeFacebook = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[self.accountStore requestAccessToAccountsWithType:accountTypeFacebook options:options
completion:^(BOOL granted, NSError *error) {
if(granted) {
self.accountsArray = [self.accountStore accountsWithAccountType:accountTypeFacebook];
dispatch_sync(dispatch_get_main_queue(), ^{
[self updateTable:self.accountsArray];
});
} else {
NSLog(#"error: %#",error);
}
}];
If the user selects "cancel" in the modal popup that prompts for access to Facebook accounts, is it possible to prompt the user again the next time the app needs this access?
Currently, if the user first selects "cancel", the user must then go into the Settings app and manually change the permission to use facebook within the app. I am not attempting to change this permission directly, I just want to prompt the user for access multiple times.
Related
I want to programatically fetch the value of "Allow these Apps to use your account" in Twitter Settings Page and if it is disabled open the Settings Page so the user can manually change the value.
I have tried to open settings page in Twitter in iOS 8.1 using the code :
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#”prefs:root=TWITTER”]];
But it does nothing in iOS 8+.Does anyone know how to fetch this value programatically and redirect to Settings Page of twitter ?
prefs scheme does not work anymore, all your app can do now is open an app preferences via UIApplicationOpenSettingsURLString constant. see this answer.
Note also, that requestAccessToAccountsWithType:options:completion: method will trigger a permission dialog if this is a first call. So the better way will be to fail gracefully, when you try to do something with twitter. The permissions dialog should be a result of user action, so it will not be confusing for him.
Try Following...
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:
ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType options:nil
completion:^(BOOL granted, NSError *error)
{
if (granted == YES)
{
NSLog(#"Twitter Access");
}
else
{
NSLog(#"No Twitter Access");
}
}];
Edit: No work around yet, but Facebook in there own SDK seemed to have deprecated using the system FB sign-on. I tried the latest SDK, and it just completely ignores the system sign-on. Unfortunately I can' used the latest SDK as, despite using the "legacy" setting, it still returns a token which doesn't give me what I need. It might be useful to see how they're bypassing the system settings though!
Original Q
I have an app which is using Facebook to authenticate.
I'm using the Facebook SDK (3.13.1 - the last pre api v2 version)
If I attempt to authenticate, as long as I don't have a FB account setup in the system settings, everything works fine. The app launches either the FB mobile app or mobile Safari to login an prompts me to grant the necessary permissions.
As soon as there is a system account setup, it fails silently. I'm deleting the app in between runs to ensure that the lack of permissions isn't persisting. If I run some of the FB sample apps which come with the SDK, they prompt for permission just fine, so it is obviously a problem with my app or the configuration of the Facebook app.
I've looked at these 2 similar questions:
Facebook Login - If user account is present (and app is not installed) login fails
Facebook Login error when facebook account is already configured in system preferences
but neither provides an answer that works in my situation. (E.g I do have bundle identifiers configured in the Facebook App)
I've tried using my own custom login code (based on the Facebook guide) and using the FBLoginView, both with the same effect.
I've also tried using ACAccountStore to make the request directly to the system store, with the same effect. Any ideas?
I'll include some code, but I'm fairly certain the code is not the problem - it all works fine if the system FB account is not configured: (i've changed my FacebookAppIDkey here)
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *facebookType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
NSDictionary *options = #{ ACFacebookAppIdKey: #"123",
ACFacebookPermissionsKey: #[#"public_profile", #"user_likes", #"user_friends", #"email"],
ACFacebookAudienceKey: ACFacebookAudienceFriends};
[accountStore requestAccessToAccountsWithType:facebookType options:options completion:^(BOOL granted, NSError *error) {
if (granted) {
NSArray *accounts = [accountStore
accountsWithAccountType:facebookType];
id facebookAccount = [accounts lastObject];
DLog(#"%#", facebookAccount);
}
else
{
if (error)
{
DLog(#"%#", error.localizedDescription);
}
}
}];
Using the SDK:
[FBSession openActiveSessionWithReadPermissions:#[#"public_profile", #"user_likes", #"user_friends", #"email"]
allowLoginUI:YES
completionHandler:
^(FBSession *session, FBSessionState state, NSError *error) {
AppDelegate* appDelegate = (AppDelegate *) [UIApplication sharedApplication].delegate;
[appDelegate sessionStateChanged:session state:state error:error];
if ([FBSession activeSession].isOpen) {
__typeof__(self) strongSelf = weakSelf;
strongSelf.facebookToken = session.accessTokenData.accessToken;
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
completion(error,(NSDictionary *)result);
}];
} else {
completion(error,nil);
}
}];
The problem may is because you are already logged in but doesn't have an access token.
So you have to check the condition
if(appDelegate.session.state == FBSessionStateCreatedTokenLoaded) .
Hope the following code will help.
VNSAppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (!appDelegate.session.isOpen) {
// create a fresh session object
appDelegate.session = [[FBSession alloc] init];
// if we don't have a cached token, a call to open here would cause UX for login to
// occur; we don't want that to happen unless the user clicks the login button, and so
// we check here to make sure we have a token before calling open
if (appDelegate.session.state == FBSessionStateCreatedTokenLoaded) {
// even though we had a cached token, we need to login to make the session usable
[[appDelegate.session initWithPermissions:appDelegate.permissions]openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
// we recurse here, in order to update buttons and labels
[self updateView];
}];
}
I request access to Twitter account by this code:
-(void)requestAccessToTwitterAccounts{
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
if (granted)
{
NSLog(#"Granted");
_twAccounts = [accountStore accountsWithAccountType:accountType];
if (_twAccounts.count > 0){
NSLog(#"%#",_twAccounts);
} else {
NSLog(#"No Accoutn");
}
} else{
NSLog(#"Not Grand");
}
}];
}
The problem is that I call this method again when user choose "Don't Allow" but it just work OK 1time.
1st time, it ask for permission, if user choose "Don't Allow", the asking alert view not display again. I just see the log "Not Grand".
How can we renew request access to twitter again so that the alertView for permission display again?
I think you only can say (message if there are no access) user to allow app to use twitter again in twitter section in settings app.
Go to settings and enable Allow these apps to use your account switch for respective application Manually. Once you tapped Don't allow then the switch become off. Make the user to enable the Switch.
As par My Knowledge this is Not Possible once use can select "Don't Allow" that not asking again. This is a same like Address-book Permission Alert or Location Permission.
So you can set Manually Alert Massage for allow Access From setting and that need Manually open Setting view and Logged in From there.
I'm trying to use iOS Social.framework to share to Facebook. However, most users will not have Facebook setup in Settings>Facebook so therefore Facebook doesn't show up when you bring up a UIActivityViewController, it just isn't listed. (See UIActivity with no settings for Facebook or just google "facebook doesn't show in UIActivityViewController," there's plenty of people trying to solve this problem.)
Our app already uses the Facebook SDK so I can get at the Facebook account info, so I thought I would just get the info and then save the info in Settings>Facebook. Here's my code. (Which I got from When do we use saveAccount:(ACAccount *)account of ACAccountStore class? and iOS requestAccessToAccountsWithType is Not Showing Permission Prompt / NSAlert)
- (void)storeAccountWithAccessToken:(NSString *)token secret:(NSString *)secret {
if (self.accountStore == nil) {
self.accountStore = [[ACAccountStore alloc] init];
}
//We start creating an account by creating the credentials object
ACAccountCredential *credential = [[ACAccountCredential alloc] initWithOAuthToken:token tokenSecret:secret];
ACAccountType *acctType =[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
ACAccount *newAccount = [[ACAccount alloc] initWithAccountType:acctType];
//Here we assign credentials and now can save account
newAccount.credential = credential;
NSDictionary *options = [[NSDictionary alloc] initWithObjectsAndKeys:
[VVEnvironment stringForKey:kVVEnvironmentKeyFacebookAppID], (NSString *)ACFacebookAppIdKey,
[NSArray arrayWithObject:#"basic_info"], (NSString *)ACFacebookPermissionsKey,
ACFacebookAudienceEveryone, (NSString *)ACFacebookAudienceKey,
nil];
[_accountStore requestAccessToAccountsWithType:acctType options:options completion:^(BOOL granted, NSError *error) {
if (granted == YES) {
[self.accountStore saveAccount:newAccount withCompletionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"the account was saved!");
}
else {
if ([error code] == ACErrorPermissionDenied) {
NSLog(#"Got a ACErrorPermissionDenied, the account was not saved!");
}
NSLog(#"the account was not saved! %d, %#", [error code], error);
}
}];
}
else {
NSLog(#"ERR: %# ",error);
}
}];
}
I added the call to requestAccessToAccountsWithType there because without I was getting a ACErrorPermissionDenied back from saveAccount. When I run this I do see my app slide briefly aside for the Facebook dialog (if I delete my app on Facebook's website it does bring up the full dialog asking me for permissions which I grant.)
The problem is that granted is always NO, so I never get a chance to save the account. What am I missing here?
I am running this on a real device that has the Facebook App installed and setup.
I'd appreciate any help on this, thanks!
There is no solution available for this. iOS native facebook applications are not allowed to write or save account to ACAccountStore. It only allow to access account from the ACAccountStore. iOS only allow to store 1 facebook account at a time. Try to do these steps you will understand this easily,
Add a facebook account to settings App and try to get permission to access it. It will grand permission.
Remove account and try to get the permission it will deny access.
Add a facebook account and get access and try to save new account to ACAccountStore, It will say that Native applications are not allowed to save account to ACAccountStore.
The proposed solution is, Add the account to settings App and login with it and Share using Social framework or presentOSIntegratedDialog.
i have used tweet sheet to tweet in my app,which works fine but can’t log out after setting ..i have to re launch the app to tweet
but what i want is to make a separate login button but in twitter is it possible to login and log out from twitter inside app?
Thanks loads in advance :)
I don't think that this is possible. You have to logout in your phones Settings.
You have to provide your own UI for Twitter login. E.g. once user entered twitter credentials you can first add Twitter account and then call Tweet sheet.
I doubt if log out or delete account is possible using SDK.
Sample code to add twitter account:
ACAccountStore *store = [[ACAccountStore alloc] init] ;
ACAccountType *twitterType = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[store requestAccessToAccountsWithType:twitterType withCompletionHandler:^(BOOL granted, NSError *error) {
if(granted) {
ACAccount *twitterAccount = [[ACAccount alloc] initWithAccountType:[store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter]];
ACAccountCredential *outhCredential = [[ACAccountCredential alloc] initWithOAuthToken:token.key tokenSecret:token.secret];
twitterAccount.credential = outhCredential;
[store saveAccount:twitterAccount withCompletionHandler:^(BOOL success, NSError *error) {
if(success)
{
[self performSelectorOnMainThread:#selector(showTweetSheet) withObject:nil waitUntilDone:NO];
}
}];
[outhCredential release];
[twitterAccount release];
[store release];
}
// Handle any error state here as you wish
}];