I have two questions related in iOS vs Facebook API.
1) How to customise the facebook login view when user click the login btn to get user data.
2) In my application i want to use the facebook API. In this way i can able to retrieve the Users Data in this below method. But how can i save these users datas in my app locally.
Highly appreciated for your help !!!
[FBSession openActiveSessionWithReadPermissions:#[#"email",#"user_location",#"user_birthday",#"user_hometown"]
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
switch (state) {
case FBSessionStateOpen:
[[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);
NSLog(#"FB user location:%#",user.location);
NSLog(#"FB user username:%#",user.username);
NSLog(#"FB user gender:%#",[user objectForKey:#"gender"]);
NSLog(#"email id:%#",[user objectForKey:#"email"]);
NSLog(#"location:%#", [NSString stringWithFormat:#"Location: %#\n\n",
user.location[#"name"]]);
self.fbUserDataDict = [NSDictionary dictionaryWithDictionary:user];
}
}];
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
} ];
How about using something like Parse to store them locally ? You can also use SQLite. Though do you mind expanding a bit on what would you like to do ? Just store them locally ?
Related
Using SDK 3.22.0.
if (FBSession.activeSession.isOpen) {
[FBSession.activeSession
requestNewPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
NSLog(#"error = %#", error);
NSLog(#"session open = %d", session.isOpen);
NSLog(#"session.permissions = %#", session.permissions);
NSLog(#"session.accessTokenData.declinedPermissions = %#", session.accessTokenData.declinedPermissions);
}];
}
else {
[FBSession
openActiveSessionWithPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
NSLog(#"error = %#", error);
NSLog(#"session open = %d", session.isOpen);
NSLog(#"status = %lu", status);
NSLog(#"session.permissions = %#", session.permissions);
NSLog(#"session.accessTokenData.declinedPermissions = %#", session.accessTokenData.declinedPermissions);
}];
}
I'm testing with a user that doesn't have yet publish permissions and never declined it either. On FB Apps Settings on this account, the App Visibility is set to "Friends" and publishing permissions are not even on the settings list as they are for other users/apps.
In both cases of the code, the FB app opens and returns to my app immediately, without asking permissions. Response of declinedPermissions is an array with publish_actions.
My expectation is that FB app will ask the user to approve publishing.
I got reports from multiple users that experienced the same issue - not being able to add publish permissions, but some are able to get the permission.
One thing to add is that I had the same issue before submitting the app for FB approval with users outside of the test group, but when app got approved it started working for those users. Now it seems like the problem persists even when the app is approved, just for random users.
Am I doing anything wrong with the way I'm asking for permissions?
Looks like this worked:
- (BOOL)hasWritePermissions {
if (!FBSession.activeSession.isOpen) return NO;
return [FBSession.activeSession.permissions indexOfObject:#[#"publish_actions"]] != NSNotFound;
}
- (void)requestWritePermissions:(void(^)(BOOL status, NSError *error))callback {
if (self.hasWritePermissions) {
callback(YES, nil);
return;
}
if (FBSession.activeSession.isOpen) {
[FBSession.activeSession
requestNewPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
NSLog(#"error = %#", error);
NSLog(#"session open = %d", session.isOpen);
NSLog(#"session.permissions = %#", session.permissions);
NSLog(#"session.accessTokenData.declinedPermissions = %#", session.accessTokenData.declinedPermissions);
if (self.hasWritePermissions) {
callback(YES, nil);
}
else {
callback(NO, error);
}
}];
}
else {
[FBSession
openActiveSessionWithPublishPermissions:#[#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
NSLog(#"error = %#", error);
NSLog(#"session open = %d", session.isOpen);
NSLog(#"status = %u", status);
NSLog(#"session.permissions = %#", session.permissions);
NSLog(#"session.accessTokenData.declinedPermissions = %#", session.accessTokenData.declinedPermissions);
[self requestWritePermissions:callback]; // this time, with an open session
}];
}
}
If there's no session, I run openActiveSessionWithPublishPermissions and then run again requestNewPublishPermissions.
Issue is that openActiveSessionWithPublishPermissions was firing the callback without even going to Facebook app for more permissions (looks like FB bug, will report), but this approach seems to solve it.
Another issue I found is that session.permissions are not always reflecting the permissions on Facebook. The only way I found to ensure I have the latest permissions is to issue an API request:
[FBRequestConnection startWithGraphPath:#"/me/permissions" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
and check the result.data array for granted/declined permissions.
I had a similar issue with this method. I ended up opening the session with a full set of permissions (read & write ) and it solved my problem.
-(void)requestPublishPermissionsWithCompletion:(FBHandlerComp)completion{
if (self.session.isOpen && [self.session.permissions containsObject:#"publish_actions"]){
//we have an open session and all neceassarry pemissions
completion(true,nil);
}else{
//something in missing, to account to all diffrent scenarios (missing persmission, expired tokens, changes in user sessting etc..), we reinisilise the session and request permissions
//for publish permissions we need to ask for the whole set( read& publish)
NSMutableArray *permissions = [NSMutableArray arrayWithArray:self.writePersmissions];
[permissions addObjectsFromArray:self.readPersmissions];
self.session = [[FBSession activeSession]initWithAppID:nil permissions:permissions defaultAudience:FBSessionDefaultAudienceFriends urlSchemeSuffix:nil tokenCacheStrategy:nil];
[self openFacebookSessionWithCompleteion:^(BOOL result, NSError *error) {
if (result) {
completion(true,nil);
}else{
if (LOGGING_IS_ON) DebugLog(#"could not get publish permissions- could not open session %#",error);
completion(false,nil);
}
}];
}
}
I want to fetch friend list of login user without using "FBFriendPickerViewController". So I used Graph API to do so but its not giving me the list of friends. I can login successfully and can able to fetch login user's information as well. I have followed this link https://developers.facebook.com/docs/graph-api/reference/v2.0/user/friendlists.
I have tried this code of snippet till now
-(IBAction)loginWithFacebook:(id)sender {
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];
}
else {
[FBSession openActiveSessionWithPublishPermissions:#[#"publish_actions",#"manage_friendlists",#"public_profile",#"user_friends"]
defaultAudience:FBSessionDefaultAudienceEveryone
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
[self sessionStateChanged:session state:status error:error];
}];
}
}
-(void)sessionStateChanged:(FBSession *)session state:(FBSessionState) state error:(NSError *)error
{
// If the session was opened successfully
if (!error && state == FBSessionStateOpen){
NSLog(#"Session opened");
// Show the user the logged-in UI
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
NSLog(#"%#",user);
NSLog(#"email::: %#",[user objectForKey:#"email"]);
}];
return;
}
if (state == FBSessionStateClosed || state == FBSessionStateClosedLoginFailed){
// If the session is closed
NSLog(#"Session closed");
}
// Handle errors
if (error){
NSLog(#"Error");
NSString *alertText;
NSString *alertTitle;
// If the error requires people using an app to make an action outside of the app in order to recover
if ([FBErrorUtility shouldNotifyUserForError:error] == YES){
alertTitle = #"Something went wrong";
alertText = [FBErrorUtility userMessageForError:error];
[self showMessage:alertText withTitle:alertTitle];
} else {
// If the user cancelled login, do nothing
if ([FBErrorUtility errorCategoryForError:error] == FBErrorCategoryUserCancelled) {
NSLog(#"User cancelled login");
// Handle session closures that happen outside of the app
} else if ([FBErrorUtility errorCategoryForError:error] == FBErrorCategoryAuthenticationReopenSession){
alertTitle = #"Session Error";
alertText = #"Your current session is no longer valid. Please log in again.";
[self showMessage:alertText withTitle:alertTitle];
} else {
//Get more error information from the error
NSDictionary *errorInformation = [[[error.userInfo objectForKey:#"com.facebook.sdk:ParsedJSONResponseKey"] objectForKey:#"body"] objectForKey:#"error"];
// Show the user an error message
alertTitle = #"Something went wrong";
alertText = [NSString stringWithFormat:#"Please retry. \n\n If the problem persists contact us and mention this error code: %#", [errorInformation objectForKey:#"message"]];
[self showMessage:alertText withTitle:alertTitle];
}
}
// Clear this token
[FBSession.activeSession closeAndClearTokenInformation];
}
}
Now after login I tried to fetch friend list for that I have written
- (IBAction)fetchFrinds:(id)sender {
[FBRequestConnection startWithGraphPath:#"/me/friendlists"
parameters:#{#"fields": #"id,name"}
HTTPMethod:#"GET"
completionHandler:^(
FBRequestConnection *connection,
id result,
NSError *error
) {
NSLog(#"%#",result);
}];
}
As per the Facebook Graph API 2.0 docs on Friendlists:
/{user-id}/friendlists
A person's 'friend lists' - these are groupings of friends such as "Acquaintances" or "Close Friends", or any others that may have been created. They do not refer to the list of friends that a person has, which is accessed instead through the /{user-id}/friends edge.
So, with your current request, you're getting the friend-lists rather than the list of friends.
For getting a list of friends, you need to refer to:
Facebook Graph API 2.0 docs on List of Friends
NOTE:
Facebook seems to have changed it's implementation.
You can no longer get the entire list of friends.
Now... the list will be limited to only those friends who also happen to use your app.
To quote Facebook Graph API 2.0 doc:
Permissions
A user access token with user_friends permission is required to view the current person's friends.
This will only return any friends who have used (via Facebook Login) the app making the request.
If by friendslist you mean a list of friends for the logged in user then the graph path is me/friends. Something like this works for me after you have opened an active FBSession with read permissions.
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"id,name,picture",#"fields",nil];
[FBRequestConnection startWithGraphPath:#"me/friends"
parameters:params
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
if(error == nil) {
FBGraphObject *response = (FBGraphObject*)result;
NSLog(#"Friends: %#",[response objectForKey:#"data"]);
}
}];
Note that the result of the FBRequestConnection request on success is an FBGraphObject with the required information returned for key 'data'.
You can open an active FBSession with read permission of just basic_info before making an FBRequestConnection for the list of friends.
Hope this helps
I'm using facebook-ios-sdk-3.10, Using this SDK I'll login and fetch user details from FB Its working fine for me.
This is the code I'm uisng
- (IBAction)fbLogin_click:(id)sender
{
if (AppDelegate.fbsession.state != FBSessionStateCreated) {
// Create a new, logged out session.
NSArray *permissions = [NSArray arrayWithObjects:#"offline_access", #"email", #"publish_stream", #"read_stream",#"read_friendlists",#"manage_friendlists",#"friends_about_me",#"publish_actions", nil];
// create a session object, with defaults accross the board, except that we provide a custom
// instance of FBSessionTokenCachingStrategy
AppDelegate.fbsession = [[FBSession alloc] initWithAppID:nil
permissions:permissions
urlSchemeSuffix:nil
tokenCacheStrategy:nil];
}
FBSessionLoginBehavior behavior = FBSessionLoginBehaviorForcingWebView;
if (AppDelegate.fbsession.state != FBSessionStateCreatedTokenLoaded) {
// even though we had a cached token, we need to login to make the session usable
[AppDelegate.fbsession openWithBehavior:behavior completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
if (error)
{
NSLog(#"Error");
}
[self GetFBUserDetails];
}];
}
}
-(void) GetFBUserDetails
{
if (AppDelegate.fbsession.isOpen)
{
[HUD show:YES];
// fetch profile info such as name, id, etc. for the open session
FBRequest *me = [[FBRequest alloc] initWithSession:AppDelegate.fbsession graphPath:#"me"];
self.pendingRequest= me;
[me startWithCompletionHandler:^(FBRequestConnection *connection,
NSDictionary<FBGraphUser> *user,
NSError *error) {
// because we have a cached copy of the connection, we can check
// to see if this is the connection we care about; a prematurely
// cancelled connection will short-circuit here
if (me != self.pendingRequest) {
return;
}
self.pendingRequest = nil;
// self.pendingLoginForSlot = -1;
// we interpret an error in the initial fetch as a reason to
// fail the user switch, and leave the application without an
// active user (similar to initial state)
if (error) {
return;
}
[AppDelegate.fbsession closeAndClearTokenInformation];
[FBSession.activeSession close];
[FBSession.activeSession closeAndClearTokenInformation];
FBSession.activeSession=nil;
[self FacebookCustomerRegister:user];
}];
}
}
In such case some user create Facebook account and not very his account through email, when he try to login via my app it shows empty screen after click login button, there is no action further. how can I notify the user "You not yet verify your FB account" and it not return to my app. how can I fetch the response from there ?
can anyone help me for this ?
The email address you get from Facebook using the Graph API or a FQL query is a verified email. If an account hasn't verified it's email yet it's not possible to get it.
so when you fetch user info and if you are not getting the email when you have the permission to get then user is no verified and you can show an alert or any info to user about verifying the email and information
check more detail here Is it possible to check if an email is confirmed on Facebook?
I'm trying to get a user's country, state and city using an FBGraphObject. The returned FBGraphObject contains the following piece of information:
hometown = {
id = 112118618814985;
name = "La Paz, Bolivia";
};
(My city is called La Paz, in the country Bolivia).
This could work wonderfully, if it actually would return the "state". If someone from Wichita, Kansas in the USA, ran my app, the result would be:
hometown = {
name = "Wichita, Kansas";
};
(That person's city is Wichita, in the State of Wichita, which is in the USA... The problem is the FBGraphObject doesn't tell me, this is in the USA).
When I first saw the graph object's hometown property, I immediately thought I could work with it if I just splat the string using the coma token, to get this:
La Paz
Bolivia
Then I'd immediately know that the first object represents a city, and the second one represents a country.
But for a country like the USA, while the first element would still represent a city, the second one represents an state, and therefore, I can't store the data tokenized from there.
How could I properly get a country, state, city using the FacebookSDK for iOS? I'm scratching my head because everyone who managed to do it seemed to get it to work with PHP, but I need this to work on the iPhone itself.
EDIT: For the record, this is how I'm trying to get everything:
[FBRequestConnection startForMeWithCompletionHandler:
^(FBRequestConnection *connection, id result, NSError *error) {
if(error == nil)
{
FBGraphObject<FBGraphUser, FBGraphLocation> *graph = result;
NSLog(#"%#", graph);
[[SPAccount sharedAccount] linkFacebookAccountWithGraphObject:graph
andCompletionBlock:^(BOOL linked) {}];
}
}];
And all of the following return nil:
graph.location.country
graph.country
graph.location.location.country
you can get the location through the location property on FBGraphUser. This will give you an object that conforms to FBGraphPlace. The location property on the FBGraphPlace conformer is an object that conforms to the FBGraphLocation protocol, which has properties such as:
city
country
latitude
longitude
state
street
zip
or
import FacebookSDK/FacebookSDK.h in your code
[FBSession openActiveSessionWithReadPermissions:#[#"email",#"user_location",#"user_birthday",#"user_hometown"]
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
switch (state) {
case FBSessionStateOpen:
[[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);
NSLog(#"FB user location:%#",user.location);
NSLog(#"FB user username:%#",user.username);
NSLog(#"FB user gender:%#",[user objectForKey:#"gender"]);
NSLog(#"email id:%#",[user objectForKey:#"email"]);
NSLog(#"location:%#", [NSString stringWithFormat:#"Location: %#\n\n",
user.location[#"name"]]);
}
}];
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
} ];
H,In my app a user can login to the app using facebook.I am able to login successfully using fbsession but i am not able to logout form fbsession.Once the user login to the app i have do manually log out from fbsession. but i am not able to log out from fbseesion. In my app when ever i click on login button its not directing to login page its directly showing dialog page,where as for me i have to show login page every time in my app.
here is my code
- (IBAction)facebooklogin:(id)sender
{
[FBSession openActiveSessionWithReadPermissions:#[#"email",#"user_location",#"user_birthday",#"user_hometown"]
allowLoginUI:YES
completionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
switch (state) {
case FBSessionStateOpen:
[[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(#"user :%#",user);
NSDictionary *resultdict=[[[NSDictionary alloc]initWithObjectsAndKeys:user.first_name,#"FirstName",user.last_name,#"LastName",user.last_name,#"LastName",user.birthday,#"Birthday",user.username,#"Username",[user objectForKey:#"email"],#"Email",user.id,#"FBUserId", nil]autorelease];
[[NSUserDefaults standardUserDefaults]setObject:resultdict forKey:#"FBUserDetails"];
NSString *userid=[NSString stringWithFormat:#"%##social",user.id];
[self performSelector:#selector(checkSocialNetworkingRegisteredOrNot:) withObject:userid afterDelay:0.0f];
}
}];
break;
default:
break;
}
} ];
}
/////////////////////////manually logout from fbsession ///////////
- (IBAction)logoutmanullayInbackground:(id)sender
{
[FBSession.activeSession closeAndClearTokenInformation];
[[FBSession activeSession] close];
[[FBSession activeSession] closeAndClearTokenInformation];
[FBSession setActiveSession:nil];
}
You are logging out (the fact you see the button say "Log in" again means you've successfully logged out). However, if you're using SSO (via either iOS integrated login, or the Facebook app), then when the user clicks "Log in" again, they won't be prompted (since the user on the App or device has already authorized your app).
To get around this (since you say you're making a restaurant app), you can uninstall the Facebook app (and remove the login from iOS), or you can log in with the FBSessionLoginBehaviorForcingWebView when you open the session.
See https://developers.facebook.com/docs/reference/ios/current/class/FBSession/#openWithBehavior%3AcompletionHandler%3A