I am integrating facebook login in my application. I jsut want the user to be able to login and I get his birthday and Location.
I got the latest Facebook SDK and successfully added it to my application. I also created a new application on facebook and added the key provided to my application.
I have created a button "Login with facebook" and done the following
When the user clicks the button
// handler for button click
- (IBAction)facebookLoginTouched:(id)sender {
[self openSessionWithAllowLoginUI:YES];
}
This method will show the user the facebook login page in order to get his permission
-(BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_location",
#"user_birthday",
nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self HandleLogin];
}];
}
Then if login and permission successful
- (void)HandleLogin {
if (FBSession.activeSession.isOpen) {
//THIS IS NEVER REACHED
[FBRequestConnection
startForMeWithCompletionHandler:^(FBRequestConnection *connection,
id<FBGraphUser> user,
NSError *error) {
//DO SOMETHING WITH THE USER INFO
}];
}
}
My problem:
When I click on the button the facebook page comes in correctly and I enter my username/password. It logged me correctly and I gave permission for the application to access my information. When I finish, I return to the app successfully.
However when the code reaches FBSession.activeSession.isOpen it returns false.
Why is the session still closed after I correctly logged in and gave permission?
Any help is greatly appreciated.
Thanks
You may be missing code to process the return from the Facebook app. Add the following in your app delegate implementation file:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
return [FBSession.activeSession handleOpenURL:url];
}
Related
I have had the Facebook iOS SDK running in an app I've been working on for a few months. At this point I am mostly using the SDK for SSO purposes.
Since I have started using iOS 6.0 I have been seeing an issue where the "Login to use your FB account with MY_APP" modal is blocking my current view.
The odd thing is that the user is already authenticated and apparently authorized to use my app. This is proven by the fact that I can get the user's email address and such.
It is also important to note that if I click the "X" it will close and everything is fine (user is authenticated/authorized). If I login as it tells me, it shows the "MY_APP is already authorized" modal which I cannot click the "Okay" button but I can click the "X" which again drops me back into my view with the user authenticated and authorized.
Here you can see the it:
To authenticate I am calling the following method in the appdelegate:
[appDelegate openSessionWithAllowLoginUI:YES];
The following are the relevant FB methods in my appdelegate:
// FACEBOOK STUFF
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [NSArray arrayWithObjects: #"email", nil];
return [FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
[self sessionStateChanged:session state:status error:error];
}];
}
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState)state
error:(NSError *)error {
// FBSample logic
// Any time the session is closed, we want to display the login controller (the user
// cannot use the application unless they are logged in to Facebook). When the session
// is opened successfully, hide the login controller and show the main UI.
switch (state) {
case FBSessionStateOpen: {
FBCacheDescriptor *cacheDescriptor = [FBFriendPickerViewController cacheDescriptor];
[cacheDescriptor prefetchAndCacheForSession:session];
[self sendAuthenticationStatusChangedNotification];
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
// FBSample logic
// Once the user has logged in, we want them to be looking at the root view.
[FBSession.activeSession closeAndClearTokenInformation];
//[self showLoginView];
break;
default:
break;
}
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// FBSample logic
// We need to handle URLs by passing them to FBSession in order for SSO authentication
// to work.
return [FBSession.activeSession handleOpenURL:url];
}
EDIT 1
I noticed that this is happing on one of my phones but not the other. The phone that wasn't working had an older version of the FB app installed. Updating the FB app stopped this issue from happening. I am still interested in a fix to avoid others from experiencing the same issue.
EDIT 2
The issue went away for a little but now is back even with the new facebook app installed. Please help!
The problem for me actually turned out to be a silly one. I was calling
[appDelegate openSessionWithAllowLoginUI:YES];
two times due to a button click event that was wired up twice. As soon as it was only being called once, the issue went away!
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:
^(FBSession *session,
FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
Well, after a while an alert show us saying that my application tries to access facebook and ask whether it's allowed or not.
However, that alert shows up AFTER completion handler is reached.
State is already FBSessionStateClosedLoginFailed by that time.
What should I do? Works fine in simulator.
Actually scrumptious sample in face book also fail on my iPhone. But I have facebook apps installed and logged in.
Facebook Login checklist:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [FBSession.activeSession handleOpenURL:url];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// We need to properly handle activation of the application with regards to SSO
// (e.g., returning from iOS 6.0 authorization dialog or from fast app switching).
[FBSession.activeSession handleDidBecomeActive];
}
- (void)applicationWillTerminate:(UIApplication *)application {
// if the app is going away, we close the session object; this is a good idea because
// things may be hanging off the session, that need releasing (completion block, etc.) and
// other components in the app may be awaiting close notification in order to do cleanup
[FBSession.activeSession close];
}
In my sessionStateChanged: I am doing this
switch ( state ) {
case FBSessionStateOpen:
[[Facebook _instance] fbDialogLogin:session.accessToken expirationDate:session.expirationDate];
break;
case FBSessionStateClosed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
case FBSessionStateClosedLoginFailed:
break;
default:
NSLog(#"FBSessionStateUnknown: %d", state);
break;
}
And dont forget to make sure that your FacebookAppID and BundleID is the same as the one you create in Facebook Developer Dashboard!
I'm completely new to development in Game Center. I have watched the videos in WWDC and looked at the developer website. They suggest I enter code like this for iOS 6:
- (void) authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil)
{
[self showAuthenticationDialogWhenReasonable: viewController
}
else if (localPlayer.isAuthenticated)
{
[self authenticatedPlayer: localPlayer];
}
else
{
[self disableGameCenter];
}
}];
}
I have copied this into the app delegate.m file, however it does not like it, showing errors like expecting a ] after [self showAuthenticationDialogWhenReasonable: viewController
} amongst others.
Can anyone please tell me how to authenticate the user for game center in iOS 6?
To get an introduction to GameKit, there are samples available from apple, for example:
https://developer.apple.com/library/ios/#samplecode/GKLeaderboards/Introduction/Intro.html.
In your code you are missing the closing "]", but of course you need more than just this function to connect to the gameCenter. Best start with one of the samples.
Apple has posted incorrect code, the ]; towards the end of the code belongs at the end of this line [self showAuthenticationDialogWhenReasonable: viewController
this code is not needed because this is just explaining how the method authenticateLocalPlayer works inside of Gamekit
Here's what I did without having to use the deprecated methods:
Set the authentication handler immediately in the AppDelegate by calling the function below (I put it in a singleton helper object). At this time, there is no view controller from which to show the login view controller, so if authentication fails, and the handler gives you a view controller, just save it away. This is the case when the user is not logged in.
- (void)authenticateLocalUserNoViewController {
NSLog(#"Trying to authenticate local user . . .");
GKLocalPlayer *_localPlayer = [GKLocalPlayer localPlayer];
__weak GKLocalPlayer *localPlayer = _localPlayer; // Avoid retain cycle inside block
__weak GCHelper *weakself = self;
self.authenticationViewController = nil;
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
if (viewController) {
NSLog(#"User not logged in");
weakself.authenticationViewController = viewController; // save it away
} else if (localPlayer.authenticated) {
[[GKLocalPlayer localPlayer] unregisterListener:self];
[[GKLocalPlayer localPlayer] registerListener:self];
NSLog(#"Local player %# (%#) authenticated. ID = %#",localPlayer.alias, localPlayer.displayName, localPlayer.playerID);
} else {
// Probably user cancelled the login dialog
NSLog(#"Problem authenticating %#", [error localizedDescription]);
}
};
}
Then, once your main screen has loaded, and the user wants to press a button the start an online game, present the login view controller that you stashed away earlier. I put this in another method in my helper class. When the user logs in, it will trigger an execution of your original authentication block, but the viewcontroller parameter will be nil.
-(BOOL) showGameCenterLoginController:(UIViewController *)presentingViewController {
if (self.authenticationViewController) {
[presentingViewController presentViewController:self.authenticationViewController animated:YES completion:^{
}];
return YES;
} else {
NSLog(#"Can't show game center view controller!");
return NO; // Show some other error dialog like "Game Center not available"
}
}
With the release of Facebook SDK 3.1 it has a class which launches the Facebook Native Dialog for Post in iOS 6.
Below is the code for it.
[FBNativeDialogs presentShareDialogModallyFrom:currentController initialText:nil image:nil url:nil handler:^(FBNativeDialogResult result, NSError *error) {
//Print Error
}];
Error Domain=com.facebook.sdk Code=7 "The operation couldn’t be completed. (com.facebook.sdk error 7.)" UserInfo=0x1e5e0930 {com.facebook.sdk:NativeDialogReasonKey=com.facebook.sdk:NativeDialogNotSupported
So, I tried to login first using the following code and then launch the FBNativeDialog. But, it does not enter the completion handler, when Okay button is pressed of Facebook permission window in Safari.
AppDelegate *appDelegate=[[UIApplication sharedApplication] delegate];
appDelegate.session = [[FBSession alloc] initWithPermissions:[NSArray arrayWithObjects:#"publish_stream", nil]];
[appDelegate.session openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
switch (status) {
case FBSessionStateOpen:
[FBNativeDialogs presentShareDialogModallyFrom:currentController initialText:nil image:nil url:nil handler:^(FBNativeDialogResult result, NSError *error) {
NSLog(#"Dialog Error= %#",error);
}];
break;
default:
break;
}
}];
when Okay button is pressed of Facebook permission window in Safari
You need to set up the Facebook account on the iOS 6 device/simulator in order to use the native share dialogs. Once you have done so, you will get native iOS permissions dialogs as well so there should be no app switching to Safari to login. See my similar response to http://facebook.stackoverflow.com/a/12681352/1712979
I'm trying to post a simple url to facebook from within my Native iOS App. What I do is this:
facebook = [[Facebook alloc] initWithAppId:FB_APP_ID andDelegate:delegate];
then at some point
[facebook authorize:permissions];
at this point my app quits and it gets me to safari and to the permissions page instead of presenting me a login-dialog (inside my app) where I login and then hit post or something an just post to my wall.
I'm pretty sure this is a simple question but since this is the first time I'm doing facebook integration it is a pain for me configuring it and the docs don't help to much.
Any help is appreciated! Thanks!
If you definitely need to remove redirection to Safari or Facebook app, you should open the FBConnect Facebook.h class and find the following method:
- (void)authorizeWithFBAppAuth:(BOOL)tryFBAppAuth
safariAuth:(BOOL)trySafariAuth {
there you need to state that you do not want to be redirected anywhere, to do that set those two bools to NO
- (void)authorizeWithFBAppAuth:(BOOL)tryFBAppAuth
safariAuth:(BOOL)trySafariAuth {
tryFBAppAuth = NO;
trySafariAuth = NO;
Next, to post something to wall, you have two options. One is broken - the standard facebook dialog window, which will bring the keyboard BEHIND the actual webview once you show any UIAlertView ANYWHERE in your application, therefore do NOT use it. Instead use your own custom interface with a simple UITextView area and a push to wall outlet button. Here's the method that you'll need in order to post to wall from your custom view:
- (void)facebookPostToWallWithMessage:(NSString *)message {
sharedInstance.facebookDelegate = delegate;
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
message, #"message", // The status message
nil];
pushMessageRequest = [facebook requestWithGraphPath:#"me/feed"
andParams:params
andHttpMethod:#"POST"
andDelegate:self];
}
And here's the delegation methods that you'll need in order to inform users that they've posted an update or to inform them that it has failed:
- (void)request:(FBRequest *)request didLoad:(id)result {
if (request == pushMessageRequest) {
NSLog(#"message has been posted, inform delegate");
}
}
- (void)request:(FBRequest *)request didFailWithError:(NSError *)error {
if (request == pushMessageRequest) {
//failed to post message, inform delegate
//[facebookDelegate facebookFailedToPostToWallWithMessage:error.localizedDescription];
}
}