I am using the following code to login on Facebook. I am using SDK 3.5.2.
- (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: {
NSMutableDictionary *params = [[[Singleton sharedSingleton] requestParams] mutableCopy];
NSString *fbaccessToken = [session accessToken];
NSLog(#"fbaccessToken: %#", fbaccessToken);
[params setObject:fbaccessToken forKey:#"facebook_access_token"];
[params setObject:[NSString stringWithFormat:#"%d", [fbaccessToken length]] forKey:#"DEBUG_linghezza_fb_accessToken"];
[params setObject:[[FBSession activeSession] appID] forKey:#"DEBUG_appID"];
[params setObject:[[FBSession activeSession] urlSchemeSuffix] forKey:#"DEBUG_urlSchemeSuffix"];
[params setObject:[[FBSession activeSession] permissions] forKey:#"DEBUG_permessi"];
NSLog(#"%#", params);
[[[Singleton sharedSingleton] sharedClient] postPath:#"login_with_facebook.json" parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
if ([[responseObject objectForKey:#"error"] isEqualToString:#"facebook_access_token not valid"]) {
NSLog(#"closeAndClearTokenInformation");
[session closeAndClearTokenInformation];
[session close];
[FBSession setActiveSession:nil];
NSLog(#"openSessionWithAllowLoginUI");
[self openSessionWithAllowLoginUI:YES];
return;
} else {...}
...
}
- (void)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSLog(#"openSessionWithAllowLoginUI:allowLoginUI");
[FBSession sessionOpenWithPermissions:[[[Singleton sharedSingleton] initPrefs] objectForKey:#"facebook_permissions"] completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
[self sessionStateChanged:session state:status error:error];
}];
return;
}
When I change the password in Facebook, I cannot login any more. The server is receiving
{
error: {
message: "Error validating access token: The session has been invalidated because the user has changed the password.",
type: "OAuthException",
code: 190,
error_subcode: 460
}
}
Everytime I try to refresh the token, I continue to receive the old token that the server cannot validate.
The server validates it with the following OpenGraph URI:
https://graph.facebook.com/me?access_token=ACCESS_TOKEN
How shall I fix this? Thank you
Related
(IBAction)loginWithfacebookClicked:(id)sender
{
// When Clicked on Facebook Button
if (FBSession.activeSession.state == FBSessionStateOpen
|| FBSession.activeSession.state == FBSessionStateOpenTokenExtended) {
// Close the session and remove the access token from the cache
// The session state handler (in the app delegate) will be called automatically
[FBSession.activeSession closeAndClearTokenInformation];
// If the session state is not any of the two "open" states when the button is clicked
} else {
// Open a session showing the user the login UI
[FBSession openActiveSessionWithReadPermissions:#[#"email",#"user_location",#"user_birthday",#"user_hometown"]
allowLoginUI:YES
completionHandler:
^(FBSession *session, FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
}
}
Use this logic inside Facebook button click
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
//***Start : requesting for facebook login with valid permissions***
[login logInWithReadPermissions: #[#"public_profile"]
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
NSLog(#"Process error");
}
else if(result.isCancelled){
NSLog(#"Cancelled");
}
else {
//Successfully logged in
NSLog(#"Logged in");
//dictionary to represent the data to be fetched from facebook
NSDictionary *params = #{ #"fields":#"name,gender,id,picture"};
//Setting up the request parameters
FBSDKGraphRequest *requestForUserProfileDetails = [[FBSDKGraphRequest alloc]initWithGraphPath:#"me" parameters:params HTTPMethod:#"GET"];
//***Start : requesting for user profile details***
[requestForUserProfileDetails startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection ,id result, NSError* error){
if(!error)
{
//set login type as facebook
//result contains the json response sent by facebook
_socialLoginType = #"facebook";
_name = [result valueForKey:#"name"];
_gender = [result valueForKey:#"gender"];
_socialLoginKey = [result valueForKey:#"id"];
_profileImage = [[UIImage alloc]initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[[[result valueForKey:#"picture"] valueForKey:#"data"] valueForKey:#"url"]]]];
}
}];
//***End : requesting for user profile details***
}
}];
//***End : requesting for facebook login with valid permissions***
- (void)viewDidLoad
{
[super viewDidLoad];
m_allFriends = [[NSMutableArray alloc] init];
if ([[FBSession activeSession] isOpen])
{
if ([[[FBSession activeSession] permissions]indexOfObject:#"user_friends"] == NSNotFound)
{
[[FBSession activeSession] requestNewPublishPermissions:[NSArray arrayWithObject:#"user_friends"] defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session,NSError *error){
[self getFBFriendListFunc];
NSLog(#"1");
}];
}
else
{
[self getFBFriendListFunc];
NSLog(#"2");
}
}
else
{
[FBSession openActiveSessionWithPublishPermissions:[NSArray arrayWithObject:#"user_friends"]
defaultAudience:FBSessionDefaultAudienceOnlyMe
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if (!error && status == FBSessionStateOpen) {
[self getFBFriendListFunc];
NSLog(#"3");
}else{
NSLog(#"error");
}
}];
}
}
-(void)getFBFriendListFunc
{
[FBRequestConnection startWithGraphPath:#"me/friends"
parameters:nil
HTTPMethod:#"GET"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
NSLog(#"me/friends result=%#",result);
NSLog(#"me/friends error = %#", error.description);
NSArray *friendList = [result objectForKey:#"data"];
[m_allFriends addObjectsFromArray: friendList];
}];
}
I try to connect Facebook with their API, actually this code connect Facebook, Facebook ask me this application want to use your information than i confirmed. Last step, Facebook return again my application than this getFBFriendListFunc should be run but none of if/else work. Nothing display...
I get this codes on Facebook developer which code part wrong ?
Any idea ?
Thank you...
For inviting users you can use the following code after adding the facebook-sdk
[FBWebDialogs
presentRequestsDialogModallyWithSession:sharedFacebookHelper.session
message:#"Your invite message"
title:nil
parameters:nil
handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
if (error) {
// An error occurred, we need to handle the error
// See: https://developers.facebook.com/docs/ios/errors
NSLog(#"Error publishing story: %#", error.description);
} else {
if (result == FBWebDialogResultDialogNotCompleted) {
// User canceled.
NSLog(#"User cancelled.");
} else {
// Handle the publish feed callback
}
}
}];
I add this function on AppDelegate.m if this function does not exit login session never be work i hope this code help any one :)
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
BOOL wasHandled = [FBAppCall handleOpenURL:url sourceApplication:sourceApplication];
return wasHandled;
}
I am trying to get basic user information from facebook, using the following code
- (void)viewDidLoad
{
[super viewDidLoad];
if(![[FBSession activeSession] isOpen]){
NSLog(#"Creating new session");
[FBSession openActiveSessionWithPermissions:nil
allowLoginUI:NO
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self makeRequestForUserData];
}];
}else{
}
}
- (void) makeRequestForUserData
{
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if (!error) {
NSLog(#"user info: %#", result);
[self.txtDetails setText: [result string]];
//[[FBSession activeSession] closeAndClearTokenInformation];
} else {
NSLog(#"error %#", error.description);
}
}];
}
When closeAndClearToken is commented and allowLoginUI is set to NO or YES no error occurs and I get the data, problem is whether or not somebody is logged into fb, I get the data of last user who logged in. Where as when I uncomment closeAndClearToken I get following error:
error = {
code = 2500;
message = "An active access token must be used to query information about the current user.";
type = OAuthException;
};
this is a class method, with a completionHandler, where you will get the user. Just call this method anywhere and it should work, if you setup you app on facebook.
+ (void)requestFacebookDataWithCompletionHandler:(void (^)(NSDictionary *))handler {
// If the session state is any of the two "open" states when the button is clicked
if (FBSession.activeSession.state == FBSessionStateOpen
|| FBSession.activeSession.state == FBSessionStateOpenTokenExtended) {
[FBSession.activeSession closeAndClearTokenInformation];
if (handler) {
handler(nil);
}
// If the session state is not any of the two "open" states when the button is clicked
} else {
// Open a session showing the user the login UI
// You must ALWAYS ask for public_profile permissions when opening a session
[FBSession openActiveSessionWithReadPermissions:#[#"public_profile",#"email"]
allowLoginUI:YES
completionHandler:
^(FBSession *session, FBSessionState state, NSError *error) {
[[FBRequest requestForMe] startWithCompletionHandler: ^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
if (!error) {
if (handler) {
handler(user);
}
}
}];
DAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
[appDelegate sessionStateChanged:session state:state error:error];
}];
}
}
you will also have to add some methods in AppDelegate; but you will find those methods there:
https://developers.facebook.com/docs/facebook-login/ios/v2.0 . Hope it will work
I'm trying to implement Game Request/Invite. Facebook is not returning any errors and I can share status in the user timeline using the same game/app configuration.
This is my code:
// -----------------------------------------------------------------------
//Facebook login
// -----------------------------------------------------------------------
- (void)fbLoginClicked:(id)sender
{
NSLog(#"-------------------------fbButtonClicked--------------------");
[[NSNotificationCenter defaultCenter] postNotificationName:#"LoginFaceBook" object:nil];
if (!FBSession.activeSession.isOpen) {
// if the session is closed, then we open it here, and establish a handler for state changes
[FBSession openActiveSessionWithReadPermissions:nil
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
if (error) {
NSLog(#"error");
NSLog(#"message error %#", error.localizedDescription);
} else if (session.isOpen) {
NSLog(#"session is open");
[self pickFriendsButtonClick:sender];
//[self inviteFriends];
//[self publishResult];
//[self publishButtonAction];
NSLog(#"pick Friends button on click");
}
}];
}
}
// -----------------------------------------------------------------------
//Facebook pick friends
// -----------------------------------------------------------------------
- (void)pickFriendsButtonClick:(id)sender {
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: nil];
[FBWebDialogs presentRequestsDialogModallyWithSession:nil
message:[NSString stringWithFormat:#"I just smashed %d friends! Can you beat it?", score]
title:#"Smashing!"
parameters:params
handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
if (error) {
// Case A: Error launching the dialog or sending request.
NSLog(#"Error sending request.");
} else {
if (result == FBWebDialogResultDialogNotCompleted) {
// Case B: User clicked the "x" icon
NSLog(#"User canceled request.");
} else {
NSLog(#"Request Sent.");
}
}}
friendCache:nil];
}
I already checked my app settings in Facebook.
My Bundle ID is the same in my plist and I also have input my iPhone Store ID from AppStore.
And this is my code for share status on timeline, which is working great:
// -----------------------------------------------------------------------
//Share in Facebook
// -----------------------------------------------------------------------
- (void)publishResult {
// We want to upload a photo representing the gesture the player threw, and use it as the
// image for our game OG object. But we optimize this and only upload one instance per session.
// So if we already have the image URL, we use it, otherwise we'll initiate an upload and
// publish the result once it finishes.
NSLog(#"sharing operations starting");
FBRequestConnection *connection = [[FBRequestConnection alloc] init];
NSMutableDictionary<FBOpenGraphObject> *game = [FBGraphObject openGraphObjectForPost];
game[#"type"] = #"fb_sample_rps:game";
game[#"title"] = #"an awesome game of Rock, Paper, Scissors";
game[#"data"][#"player_gesture"] = #"scissor";
game[#"data"][#"opponent_gesture"] = #"paper";
game[#"data"][#"result"] = #"win";
game[#"image"] = #"http://sandbox.yoyogames.com/extras/image/name/san2/853/404853/original/Game1.jpg";
NSLog(#"game object created");
FBRequest *objectRequest = [FBRequest requestForPostOpenGraphObject:game];
[connection addRequest:objectRequest
completionHandler:^(FBRequestConnection *innerConnection, id result, NSError *error) {
if (error) {
NSLog(#"tried to share, but Error: %#", error.description);
} else {
NSLog(#"message posted");
}
}
batchEntryName:#"objectCreate"];
NSString *message = #"teste 2";
[connection addRequest:[FBRequest requestForPostStatusUpdate:message]
completionHandler:^(FBRequestConnection *innerConnection, id result, NSError *error) {
NSLog(#"Error on post update feed");
}];
[connection start];
}
Already solved.
For some reason, my friend's Facebook version is an old one and don't receive any messages. For other friends with updated Facebook layout, it's working.
I have a button to share a link. I'm using basically two calls:
openActiveSessionWithReadPermissions and requestNewPublishPermissions.
So this is the button action:
- (IBAction) shareFacebookButtonAction:(id)sender
if (![[FBSession activeSession] isOpen])
{
NSArray *permissions = #[#"read_friendlists", #"email"];
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error)
{
if (FB_ISSESSIONOPENWITHSTATE([session state]))
{
[self _prepareShare];
}
else
{
// show alert view with error
}
}];
}
else
{
[self _prepareShare];
}
}
and with this I'm asking for publish permission, if no permissione are found in session
-(void) _prepareShare;
{
if ([FBSession.activeSession.permissions
indexOfObject:#"publish_actions"] == NSNotFound)
{
[FBSession.activeSession
requestNewPublishPermissions:
[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error)
{
if (!error)
{
[self _share];
}
else
{
//error
}
}];
} else
{
[self _share];
}
}
_share just posts something
-(void) _share;
{
NSMutableDictionary *params_dict = [NSMutableDictionary dictionary];
// setting some params
[FBRequestConnection startWithGraphPath:#"me/feed" parameters:params_dict HTTPMethod:#"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
if (result)
{
// sharing succedeed, do something
}
else if (error)
{
//sharing failed, do something else
}
}];
}
First time I try to share (already logged on FB in iOS6 and app already authorized) completion handler of openActiveSessionWithReadPermissions is being called twice:
once with FBSessionStateOpen and once with FBSessionStateOpenTokenExtended (from the openSessionForPublishPermissions call).
As a consequence, _share is also called twice, first time in the else part of _prepareShare (if I already have publish permissions) and the second time in the completion handler of openSessionForPublishPermissions.
So I have a double post on Facebook wall, just the first time I ever share in the app. I also had a crash report for FBSession: It is not valid to reauthorize while a previous reauthorize call has not yet completed (I couldn't be able to make it happen again).
What is the proper way to handle this situation?
It appears that by design, Facebook SDK retains references to block handlers, even after they have been called. Thus, in your call to openActiveSessionWithReadPermissions the completion handler may be called numerous times, in case the session state changes. See Facebooks comment on this issue here.
As a work around, you might want to implement your own mechanism that ensures the handler is fired only once:
__block FBSessionStateHandler runOnceHandler = ^(FBSession *session,
FBSessionState status,
NSError *error) { /* YOUR CODE HERE */ };
...
[FBSession openActiveSessionWithReadPermissions:YOUR_PERMISSIONS
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
if (runOnceHandler) {
runOnceHandler(session, status, error);
runOnceHandler = nil;
}
}
];
You Can use this
- (IBAction)facebookBasti:(id)sender {
if(FBSession.activeSession.isOpen){
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
NSLog(#" Email = %#",[user objectForKey:#"email"]);
}
}];
NSLog(#"POST TO WALL -- %#",FBSession.activeSession.accessToken);
[self publishFacebook];
}
else {
// try to open session with existing valid token
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"publish_actions",#"email",
nil];
FBSession *session = [[FBSession alloc] initWithPermissions:permissions];
[FBSession setActiveSession:session];
if([FBSession openActiveSessionWithAllowLoginUI:NO]) {
// post to wall
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (!error) {
NSLog(#" Email = %#",[user objectForKey:#"email"]);
}
}];
NSLog(#"POST TO WALL -- %#",FBSession.activeSession.accessToken);
[self publishFacebook];
} else {
// you need to log the user
NSLog(#"login");
[FBSession openActiveSessionWithPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
NSLog(#"POST TO WALL -- %#",FBSession.activeSession.accessToken);
[self publishFacebook];
}];
}
}
}
and publishFacebook method
-(void)publishFacebook
{
NSMutableDictionary *postParams2= [[NSMutableDictionary alloc] initWithObjectsAndKeys:
haberLink, #"link",
#"abc.com", #"name",
title, #"caption",
desc, #"description",
nil];
[FBRequestConnection
startWithGraphPath:#"me/feed"
parameters:postParams2
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
NSString *alertText;
if (error) {
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
} else {
alertText = [NSString stringWithFormat: #"Shared Facebook"];
[[[UIAlertView alloc] initWithTitle:#"Shared Facebook"
message:alertText
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil]
show];
}
}];
}
Please read Upgrading from 3.0 to 3.1, in particular the paragraph Asking for Read & Write Permissions Separately. It seems like Facebook SDK is not meant to be used this way.
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.
and
It is important that you do not simply attempt to call the two individual methods back-to-back to replace either of the deprecated functions.
I wonder how you managed to solve this issue. BTW, I get the same crash report (FBSession: It is not valid to reauthorize while a previous reauthorize call has not yet completed).