I'm making a "FBRequestConnection" to get all the friends that play the game...
When I update the SDK of Facebook to the last one, this stop working. Because It was working before.
I have no respond, no success, no error. Any ideas?
NSString *query = #"SELECT uid FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()) AND is_app_user = 1";
// Set up the query parameter
NSDictionary *queryParam = [NSDictionary dictionaryWithObjectsAndKeys:query, #"q", nil];
// Make the API request that uses FQL
[FBRequestConnection startWithGraphPath:#"/fql"
parameters:queryParam
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error) {
if (error) {
[self debug:[NSString stringWithFormat:#"Error: %#", [error localizedDescription]]];
} else {
[self debug:[NSString stringWithFormat:#"Result: %#", [result objectForKey:#"data"]]];
}
}];
-(void)fbLogin {
if (!_session.isOpen) {
// create a fresh session object
_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 (_session.state == FBSessionStateCreatedTokenLoaded) {
// even though we had a cached token, we need to login to make the session usable
[_session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
// we recurse here, in order to update buttons and labels
[[NSNotificationCenter defaultCenter] postNotificationName:#"fbConnected" object:nil];
}];
}
[self populateUserDetails];
}
}
Thanks
Open the session with:
[FBSession.activeSession openWithCompletionHandler:^(FBSession * session, FBSessionState state, NSError * error){
if (!error){
}
}];
Related
I am trying to develop a simple app, which, retrieves data from Facebook, when the user connects to it.
I tried this code for it.
NSArray *permissions = [[NSArray alloc] initWithObjects:#"user_birthday",#"user_hometown",#"user_location",#"email",#"basic_info", nil];
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
}];
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSLog(#"%#", [result objectForKey:#"gender"]);
NSLog(#"%#", [result objectForKey:#"hometown"]);
NSLog(#"%#", [result objectForKey:#"birthday"]);
NSLog(#"%#", [result objectForKey:#"email"]);
}];
But when I run this code, it gives an error "FBSDKLog: Error for request to endpoint 'me': An open FBSession must be specified for calls to this endpoint."
Thanks in advance, really appreciate your help.
The error is very appropriate, what it is trying to say is that request connection method should be called once the session is open.
Now your
[FBSession openActiveSessionWithReadPermissions:permissions
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
}];
method returns BOOL value true or false to specify you wether session is open or not(it tries to open synchronously). So first check the result of this call and the put it inside the code for fetching info. For eg.
if (FBSession.activeSession.isOpen)
{
[FBRequestConnection startForMeWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
NSLog(#"%#", [result objectForKey:#"gender"]);
NSLog(#"%#", [result objectForKey:#"hometown"]);
NSLog(#"%#", [result objectForKey:#"birthday"]);
NSLog(#"%#", [result objectForKey:#"email"]);
}];
}
This should remove your error, but you still may not get the results.You may or may not get result on the very first call to this code but whenever the code for completion handler will be called, this method FBRequestConnection will also get called and at that time you'll get the results as it is an asynchronous call.
If it still doesn't work try this
if (FBSession.activeSession.isOpen)
{
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if (error)
{
NSLog(#"error:%#",error);
}
else
{
// retrive user's details at here as shown below
NSLog(#"FB user first name:%#",user.first_name);
NSLog(#"FB user last name:%#",user.last_name);
NSLog(#"FB user birthday:%#",user.birthday);
}
}];
`(void)fbAccountConfigureWithBlock:(void (^)(id, NSString *))block
{
_block_data=block;
if(![SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook])
{
dispatch_async(dispatch_get_main_queue(), ^{
[self showAlertMessage:#"" message:#"Please go to settings and add at least one facebook account."];
_block_data(nil,nil);
});
return;
}
ACAccountStore *store = [[ACAccountStore alloc]init];
ACAccountType *accountType = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[store requestAccessToAccountsWithType:accountType
options:#{ACFacebookAppIdKey : FacebookAppId,
ACFacebookAudienceKey : ACFacebookAudienceFriends,
ACFacebookPermissionsKey : #[#"email"]}
completion:^(BOOL granted, NSError *error)
{
if(granted){
NSArray *array = [store accountsWithAccountType:accountType];
if(!array.count){
dispatch_sync(dispatch_get_main_queue(), ^{
[self showAlertMessage:#"" message:#"Please go to settings and add at least one facebook account."];
_block_data(nil,nil);
});
}
else{
ACAccount *account = array[0];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:[NSURL URLWithString:#"https://graph.facebook.com/me"]
parameters: #{#"fields":#"id,first_name,last_name,name,email,picture.height(180).width(180)"}];
[request setAccount:account];
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if(!error){
NSDictionary *userData = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSLog(#"Facebook user data ----> %#",userData);
dispatch_async(dispatch_get_main_queue(), ^{
if(userData[#"error"] != nil)
[self attemptRenewCredentials:store account:account];
else
_block_data(userData,nil);
});
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
[self showAlertMessage:#"" message:error.localizedDescription];
_block_data(nil,nil);
});
}
}];
}
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[self showAlertMessage:#"" message:#"We need permission to access your facebook account in order make registration."];
_block_data(nil,nil);
});
}
}];
}`
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 currently have a problem with my iOS application because I don't seem to be able to send requests to people...
Here is the code that I have:
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:nil];
if([FBSession activeSession].isOpen) {
[FBWebDialogs presentRequestsDialogModallyWithSession:[FBSession activeSession] message:#"Join me." title:#"Invite" parameters:params handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
NSLog(#"%#", [FBSession activeSession]);
if (error)
NSLog(#"Error sending request.");
else {
if (result == FBWebDialogResultDialogNotCompleted)
NSLog(#"User canceled request.");
else if(result == FBWebDialogResultDialogCompleted)
NSLog(#"Request: %#", resultURL);
else
NSLog(#"Error unknown.");
}
}];
}
else {
[FBSession openActiveSessionWithReadPermissions:#[#"email"] allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if(session.isOpen) {
[FBSession openActiveSessionWithPublishPermissions:#[#"publish_actions"] defaultAudience:FBSessionDefaultAudienceEveryone allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
if(session.isOpen) {
[self showRequestForFacebook];
}
}];
}
}];
}
Every time I get a Request: (null). I get a request ID but nothing on the account. I looked at the sample in the Facebook SDK and I seem to have exactly the same. However, it works with the sample and not with my code.
Is there anything to change somewhere? Is it something on developers.facebook.com?
Edit: I forgot to say that in the same application I use a SLComposeViewController to share on Facebook and it works perfectly.
Thanks a lot! :)
NSString *query2 = [NSString stringWithFormat:#"SELECT uid, name, pic_square,is_app_user FROM user WHERE is_app_user = 1 AND uid IN " #"(SELECT uid2 FROM friend WHERE uid1 = me())"];
// Set up the query parameter
NSDictionary *queryParam2 = #{ #"q": query2 };
// Make the API request that uses FQL
[FBRequestConnection startWithGraphPath:#"/fql" parameters:queryParam2 HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error)
{
if (error) {
} else {
// NSLog(#"Result: %#", result);
// Get the friend data to display
NSArray *friendInfo = (NSArray *) result[#"data"];
NSLog(#"%#",friendInfo);
self.data=friendInfo;
[self constructDictionaryOfNumbers];
// Show the friend details display
}
}];
}
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).
Using toblerpwn answer i manage to publish a picture to the application album as i wanted to.
But this works only when the application album has already been created (because i need to specify the album id).
In the other hand the requestForUploadPhoto convenience method creates the application album if it doesn't exists and publishes the picture.
So could someone help me figure out how to merge this two beheviours?
Thanks to #deepak-lakshmanan i manage to solve my problem.
The idea is to publish to the application album using /USER_ID/photos insted of /ALBUM_ID/photos; this way the album is automatically created if it doesn't exist.
So the steps to follow are:
get the publish permission
then retrieve the user id using /me
finally publish the picture to the application album with /USER_ID/photos
Here is my code in case someone struggles with this, am using Facebook SDK 3.1 for iOS:
- (void)sendRequestFacebookPublishPermission {
NSArray *permissions = [[NSArray alloc] initWithObjects:#"publish_stream", nil];
if(!FBSession.activeSession.isOpen ) {
[FBSession openActiveSessionWithPublishPermissions:permissions
defaultAudience:FBSessionDefaultAudienceFriends
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
[self requestFacebookPublishPermissionCompleted:session status:status error:error];
}];
} else if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
[FBSession.activeSession reauthorizeWithPublishPermissions:permissions
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
[self requestFacebookPublishPermissionCompleted:session status:FBSessionStateOpen error:error];
}];
} else {
[self sendRequesFacebooktUserInfo];
}
}
- (void)requestFacebookPublishPermissionCompleted:(FBSession *)session
status:(FBSessionState)status
error:(NSError *)error {
if (error) {
DLog(#"%#", error.localizedDescription);
} else {
[self sendRequesFacebooktUserInfo];
}
}
-(void)sendRequesFacebooktUserInfo {
FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
// output the results of the request
FBRequestHandler handler = ^(FBRequestConnection *connection, id result, NSError *error) {
[self requestFacebookUserInfoCompleted:connection result:result error:error];
};
// create the request object, using the fbid as the graph path
FBRequest *request = [[FBRequest alloc] initWithSession:FBSession.activeSession graphPath:#"me"];
// add the request to the connection object
[newConnection addRequest:request completionHandler:handler];
// if there's an outstanding connection, just cancel
[self.requestConnection cancel];
// keep track of our connection, and start it
self.requestConnection = newConnection;
[newConnection start];
}
- (void)requestFacebookUserInfoCompleted:(FBRequestConnection *)connection
result:(id)result
error:(NSError *)error {
// not the completion we were looking for...
if (self.requestConnection && connection != self.requestConnection) {
return;
}
// clean this up, for posterity
self.requestConnection = nil;
if (error) {
DLog(#"%#", error.localizedDescription);
} else {
FBGraphObject *dictionary = (FBGraphObject *)result;
NSString* userId = (NSString *)[dictionary objectForKey:#"id"];
[self sendRequestFacebookPublishOnAlbum:userId];
}
}
- (void)sendRequestFacebookPublishOnAlbum:(NSString*)fbId {
UIImage *imageToPost = /* get the image you need*/ ;
/*
//--- Facebook SDK convenience method : requestForUploadPhoto won't let me post image description ---//
FBRequestConnection *newConnection = [FBRequestConnection startForUploadPhoto:screenshot completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
[self requestPostCardOnFacebookCompleted:connection result:result error:error];
}];
// if there's an outstanding connection, just cancel
[self.requestConnection cancel];
// keep track of our connection, and start it
self.requestConnection = newConnection;
//-----------------------------------------------------------------------------------------------------//
*/
//--- http://stackoverflow.com/questions/12486852/facebook-ios-sdk-cannot-specify-an-album-using-fbrequests-requestforuploadphot ---//
NSString *messagePublie = laCarte.message;
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:
screenshot, #"picture",
messagePublie , #"name",
nil] ;
FBRequestConnection *newConnection = [[FBRequestConnection alloc] init];
FBRequestHandler handler = ^(FBRequestConnection *connection, id result, NSError *error) {
[self requestFacebookPublishOnAlbumCompleted:connection result:result error:error];
};
NSString *graphPath = [NSString stringWithFormat:#"%#/photos",fbId];
FBRequest *request = [[FBRequest alloc] initWithSession:FBSession.activeSession graphPath:graphPath parameters:parameters HTTPMethod:#"POST"];
[newConnection addRequest:request completionHandler:handler];
// if there's an outstanding connection, just cancel
[self.requestConnection cancel];
// keep track of our connection, and start it
self.requestConnection = newConnection;
[newConnection start];
}
- (void)requestFacebookPublishOnAlbumCompleted:(FBRequestConnection *)connection result:(id)result error:(NSError *)error {
if (self.requestConnection && connection != self.requestConnection) {
return;
}
// clean this up, for posterity
self.requestConnection = nil;
if (error) {
DLog(#"%#", error.localizedDescription);
} else {
DLog(#"%#", "Done");
}
}