Add Facebook SDK to my xCode project with Storyboard - iphone

I am following Getting Started with the Facebook SDK for iOS v3.1 to add Facebook SDK to my xCode project with Storyboard.
I did all the steps that described there.
We have a HelloFacebookSample in the Sample folder of Facebook SDK. it includes this code:
- (void)viewDidLoad {
[super viewDidLoad];
// Create Login View so that the app will be granted "status_update" permission.
FBLoginView *loginview = [[FBLoginView alloc] init];
loginview.frame = CGRectOffset(loginview.frame, 5, 5);
loginview.delegate = self;
[self.view addSubview:loginview];
[loginview sizeToFit];
}
// Post Status Update button handler; will attempt to invoke the native
// share dialog and, if that's unavailable, will post directly
- (IBAction)postStatusUpdateClick:(UIButton *)sender {
// Post a status update to the user's feed via the Graph API, and display an alert view
// with the results or an error.
NSString *name = self.loggedInUser.first_name;
NSString *message = [NSString stringWithFormat:#"Updating status for %# at %#",
name != nil ? name : #"me" , [NSDate date]];
// if it is available to us, we will post using the native dialog
BOOL displayedNativeDialog = [FBNativeDialogs presentShareDialogModallyFrom:self
initialText:nil
image:nil
url:nil
handler:nil];
if (!displayedNativeDialog) {
[self performPublishAction:^{
// otherwise fall back on a request for permissions and a direct post
[FBRequestConnection startForPostStatusUpdate:message
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
[self showAlert:message result:result error:error];
self.buttonPostStatus.enabled = YES;
}];
self.buttonPostStatus.enabled = NO;
}];
}
}
Then sample works fine, but when I want to have it on my own project, I have this problem:
It is successfully added the FBLoginView to my self.view. but when I Login and then want to post something I just go to this page:

Finally I found the problem. I needed to add these codes to my AppDelegate:
- (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];
}
- (void)applicationWillTerminate:(UIApplication *)application {
// FBSample logic
// if the app is going away, we close the session object
[FBSession.activeSession close];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// FBSample logic
// 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];
}
They were not described in the link. It could be better to let the new users know about these details.

Related

How to fetch instagram app logged in user details in ios device using our application?

This is the first time I am working on Instagram API. If the user is already having instagram app in his device, how can we fetch his user details from our application?
Right now my app is redirecting to safari and asking the instagram credentials there though I have instagram app in my iPhone where I loggedin.
Can any one please help me with this?
We need Instagram.h and Instagram.m file to fetch instagram user details.
You need a create an application in the Instagram developer site to get app id.
instagram = [[Instagram alloc] initWithClientId:APP_ID delegate:nil];
NSString *const instagramUrlScheme = #"---YourAppName---";
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { //openo
if ([urlStr hasPrefix:instagramUrlScheme]) {
//[self showAlertWithTitle:THIS_METHOD message:url.description];
return [self.instagram handleOpenURL:url];
}
}
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSString *urlStr = url.description;
if ([urlStr hasPrefix:instagramUrlScheme]) {
return [self.instagram handleOpenURL:url];
}
return NO;
}
These are the instagram delegates you need to implement.
#pragma - IGSessionDelegate
-(void)igDidLogin
{
NSLog(#"Instagram did login");
//[[self appDelegate] showAlertWithTitle:#"igDidLogin" message:#""];
// here i can store accessToken
[[NSUserDefaults standardUserDefaults] setObject:[self appDelegate].instagram.accessToken forKey:#"accessToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
//NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"users/self/followed-by", #"method", nil];
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:#"users/self", #"method", nil];
[[self appDelegate].instagram requestWithParams:params
delegate:self];
}
-(void)igDidNotLogin:(BOOL)cancelled
{
NSLog(#"Instagram did not login");
NSString* message = nil;
if (cancelled) {
message = #"Access cancelled!";
}
else {
message = #"Access denied!";
}
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:message
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}
-(void)igDidLogout
{
NSLog(#"Instagram did logout");
// remove the accessToken
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:#"accessToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
-(void)igSessionInvalidated
{
NSLog(#"Instagram session was invalidated");
}
You have to use these when you want to connect to instagram.
[self appDelegate].instagram.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"accessToken"];
[self appDelegate].instagram.sessionDelegate = self;
[[self appDelegate].instagram logout];
[[self appDelegate].instagram authorize:[NSArray arrayWithObjects:#"comments", #"likes", nil]];
Hope this helps:
As far as my knowledge when we are redirecting from our app to other app we can't access the other app details (Login details).
As long as I also do know, this is not possible.
We can't get details of the other app from our app.
You can get more info for instagram by this instagram developer link.
Hope this helps you.

how to check if already logged in Facebook in ios?

I am using "Graph Api" For Facebook login with in my app. I successfully logIn and logged out with this code
facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self.viewController];
and i using below code for already facebook logged in
if (![facebook isSessionValid]) {
[facebook authorize:permissions ];
}
My problem is i install Facebook App, and i logged in via Facebook App. then i run my app, it ask again login Facebook. how i solve this issue. it should take as a default FB app login credentials. i saw many app using this feature. anyone know the solution
1. In your AppDelegate.m file
define NSString *const FBSessionStateChangedNotification =
#"com.example:FBSessionStateChangedNotification";
replace com.example with your bundle identifier name
2.- In method
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FBSession setActiveSession:[FBSession new]];
if ([FBSession activeSession].state == FBSessionStateCreatedTokenLoaded)
{
// means u are already logged in
//do ur code
[self openSessionWithAllowLoginUI:NO];
}
else
{ //do ur code
[self openSessionWithAllowLoginUI:YES];
}
}
3. whenenever and wherever this method is called after end of switch case write
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState) state
error:(NSError *)error
{
[[NSNotificationCenter defaultCenter]
postNotificationName:FBSessionStateChangedNotification
object:session];
}
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI
{
return [FBSession openActiveSessionWithReadPermissions:#"email"
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session, FBSessionState state, NSError *error)
{
[self sessionStateChanged:session state:state error:error];
}];
}
Sorry in your appDelegate.h file it should be
extern NSString *const FBSessionStateChangedNotification;

iOS native Facebook Login fails for Mobile Safari authentication

I have a native iOS app with Facebook Login integrated. The login flow works when the native Facebook app is installed.
However, when I delete the app, the FB login fallback on FB Mobile Safari webapp. The app switching works fine, but when controls come back to my app, the state of the session is declared FBSessionStateClosedLoginFailed.
I am using Facebook SDK v3.5.2 as of June 6th, 2013
Using iPad1 iOS5.1.1
/*
* Opens a Facebook session and optionally shows the login UX.
*/
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"email",
#"publish_actions",
nil];
BOOL result = NO;
FBSession *session =
[[FBSession alloc] initWithAppID:nil
permissions:permissions
urlSchemeSuffix:#"<MySchemeSuffix>"
tokenCacheStrategy:nil];
if (allowLoginUI ||
(session.state == FBSessionStateCreatedTokenLoaded)) {
[FBSession setActiveSession:session];
[session openWithBehavior:FBSessionLoginBehaviorWithFallbackToWebView
completionHandler:
^(FBSession *session, FBSessionState state, NSError *error)
{
[self sessionStateChanged:session state:state error:error];
}];
result = session.isOpen;
}
return result;
}
/*
* If we have a valid session at the time of openURL call, we handle
* Facebook transitions by passing the url argument to handleOpenURL
*/
- (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];
BOOL urlWasHandled = [FBAppCall handleOpenURL:url
sourceApplication:sourceApplication
fallbackHandler:^(FBAppCall *call) {
// handle deep links and responses for Login or Share Dialog here
}];
return urlWasHandled;
}
/*
* Callback for session changes.
*/
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState) state
error:(NSError *)error
{
switch (state) {
case FBSessionStateOpen:
if (!error) {
if (FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
//Application specific code goes here.
}
}];
}
// We have a valid session
NSLog(#"User session found");
}
break;
case FBSessionStateClosed:
case FBSessionStateClosedLoginFailed:
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
}
I happened to fix the issue.
The bug was, I was requesting read and write permissions in the same call.
Taking out the "publish_actions" from permissions solved the issue.
I tested Facebook Login in iOS6+ through native FB login, native FB app, and webapp.
Also tested on iOS5.1.1 through native FB app, and webapp.

FBSession often fails to be at FBSessionStateCreatedTokenLoaded when returning to foreground

I am using Facebook iOS SDK3.0 (client is not ready to move to 3.1 yet), and have been having trouble to get FBSession to be at the FBSessionStateCreatedTokenLoaded when the app returns to the foreground after a longer period of time (close to a day); I don't have issue if I just send the app to background and come back to the foreground after a minute or two
my code is as follow, please let me know if I should provide further information; I have this issues across devices (4, 4S, 5) and iOS version (4.3, 5.0, 5.1, 6.0)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
if (![self openSessionWithAllowLoginUI:NO]) {
// still allow loading the public feed even though user is not logged in (the view controller will have a login button overlay)
[[self pictureFeedVC] loadFeed];
}
...
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
DEBUGLog(#"didBecomeActive");
DEBUGLog(#"FBSession is Open? %#",FBSession.activeSession.isOpen ? #"YES" : #"NO");
if (FBSession.activeSession.state == FBSessionStateCreatedOpening) {
//Dismiss login view controller
if ([self.tabBarController modalViewController]) {
[self.tabBarController dismissModalViewControllerAnimated:NO];
}
[FBSession.activeSession close];
}
}
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
BOOL result = NO;
[FBSettings setLoggingBehavior:[NSSet setWithObjects:FBLoggingBehaviorSessionStateTransitions,nil]];
NSArray *permissions = [NSArray arrayWithObjects:#"publish_actions", #"email", nil];
FBSession *session = [[FBSession alloc] initWithAppID:nil permissions:permissions urlSchemeSuffix:FB_URL_SCHEME_SUFFIX tokenCacheStrategy:nil];
if (allowLoginUI || (session.state == FBSessionStateCreatedTokenLoaded)) {
[FBSession setActiveSession:session];
[session openWithCompletionHandler:^(FBSession *session, FBSessionState state, NSError *error) {
[self sessionStateChanged:session state:state error:error];
}];
result = session.isOpen;
}
return result;
}
- (void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error
{
DEBUGLog(#"changed FB state");
switch (state) {
case FBSessionStateOpen:
if (!error) {
DEBUGLog(#"FBSessionStateOpen");
[[self pictureFeedVC] loadFeed];
}
break;
case FBSessionStateClosed:
DEBUGLog(#"FBSessionStateClosed");
case FBSessionStateClosedLoginFailed:
DEBUGLog(#"FBSessionStateClosedLoginFailed");
[session closeAndClearTokenInformation];
[self.tabBarController showFBLoginView];
break;
default:
break;
}
}
I am having problem where after extended period in the background, the DEBUGLog(#"FBSession is Open? %#",FBSession.activeSession.isOpen ? #"YES" : #"NO"); in applicationDidBecomeActive: will print a NO
more info: this app relies on Facebook login entirely, it uses facebook user ID to identify users, therefore for lots of actions I need to pass the Facebook access token so that the server can get the facebook user ID even though a lot of times those actions does not require api calls to facebook (besides getting the user ID from the access token of course). My other question is whether I need to actively do something to refresh the token or do something keep the FBSession open (if so, how?), would that be the reason why the FBSession.activeSession might not be in an open state when I return to foreground?
Thanks much in advance!

ios6 facebook integration login always FBSessionStateClosedLoginFailed never opens

this question is very similar to Facebook SDK for iOS , on iOS 4.0 device, but as I cannot make comments there, I open a new question. I think the questions are not the same:
When trying to update the facebook integration of my app to facebook 3.1 I am not getting the facebook session to open the sessionStateChanged Callback always ends up in FBSessionStateClosedLoginFailed. in my setup I have the callback in my appdelegate
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// attempt to extract a token from the url
// return [self.session handleOpenURL:url];
return [FBSession.activeSession handleOpenURL:url];
}
but it is never called! shouldn't it get called? I followed the facebook documentation and call
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [NSArray arrayWithObjects:#"publish_actions", nil];
return [FBSession openActiveSessionWithPublishPermissions:permissions
defaultAudience:FBSessionDefaultAudienceFriends
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}
I also tried
openActiveSessionWithReadPermissions with nil for the permissions as in the facebook tutorial example with the intention to reauthorize for the publish_actions permission later. same result: FBSessionStateClosedLoginFailed again.
I even tried calling
ACAccountStore *accountStore;
ACAccountType *accountTypeFB;
if ((accountStore = [[ACAccountStore alloc] init]) &&
(accountTypeFB = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook] ) ){
NSArray *fbAccounts = [accountStore accountsWithAccountType:accountTypeFB];
id account;
if (fbAccounts && [fbAccounts count] > 0 &&
(account = [fbAccounts objectAtIndex:0])){
[accountStore renewCredentialsForAccount:account completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
//we don't actually need to inspect renewResult or error.
if (error){
}
}];
}
}
before trying to open the session, but I never get it open on my ios6 device (iphone 4s). in the app I am asked for the permission, but then nothing goes on because the session is always having the state FBSessionStateClosedLoginFailed! my callback for the session state is
- (void)sessionStateChanged:(FBSession *)session
state:(FBSessionState) state
error:(NSError *)error
{
switch (state) {
case FBSessionStateOpen:
if (!error) {
// We have a valid session
NSLog(#"User session found");
}
break;
case FBSessionStateClosed:
NSLog(#"FBSessionStateClosed");
case FBSessionStateClosedLoginFailed:
NSLog(#"FBSessionStateClosedLoginFailed");
[FBSession.activeSession closeAndClearTokenInformation];
break;
default:
break;
}
[[NSNotificationCenter defaultCenter]
postNotificationName:FBSessionStateChangedNotification
object:session];
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"facebook Hinweis"
message:#"facebook Login nicht möglich, bitte versuchen Sie es erneut."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
NSLog(#"Facebook session error: %#", error.localizedDescription);
}
}
with the facebook 3.0 on ios 5 I never had an issue so my facebook app is set up correctly. I would really appreciate any help wchich enables me to just open the facebook session, did not think to run into these problems with facebook 3.1 and the docs are not helping me at this point, thx
I had the same problem, and it was because I forgot to implement
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
return [FBSession.activeSession handleOpenURL:url];
}
in my AppDelegate
While JohnG's answer is correct, that particular delegate method has now been deprecated. The correct delegate method to use is this:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [FBSession.activeSession handleOpenURL:url];
}
Placing that in my application delegate solved the issue for me. Without this, the iOS 6.0 native login would work but the Facebook app login would fail.
I had the same problem. If the user hadn't a Facebook account configured in the System Preferences the Facebook login dialog appeared and everything worked fine. But if the user had an account configured in the device I was always having a FBSessionStateClosedLoginFailed error.
It has nothing to do with handleOpenURL:url because in the "native login flow" for iOS 6 or greater there is no fast-app-change. So your app never goes to background and the URL redirection is not needed.
The problem was solved configuring the Facebook app. You need to enable the "Native iOS login" section and put the bundle ID of your app. If your app is not already in the Apple Store I'm afraid you need to set the sandbox mode to ON. Once your app is published in the Apple Store I think you need to put the sandbox mode to OFF and set the Apple Store ID in the Facebook configuration.
Even i can't comment so writing it as answer .
I am not sure , let me analyze potential reasons
1) you said: "but it is never called! shouldn't it get called?" -- for
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
to get called , in the info.plist file , url scheme should be set properly i.e go to URL types-->Item0-->URL Schemes--->Item 0 the value here should be fbAPPID i.e fb append with your actual facebookappID [FacebookAppID could also be present in the info.plist or hard coded in code].
2)You said:
"sessionStateChanged Callback always ends up in FBSessionStateClosedLoginFailed"
In the sessionStateChanged switch method check the state of session and if it created or createdTokenLoaded then try to open the session.
Note:[FBSession openActiveSessionWithPublishPermissions ....] which is a static method will create a new session and is set to FBSession.activeSession where as openWithCompletionHandler is an instance method which can work only if the session is already created .
case FBSessionStateCreated:
case FBSessionStateCreatedTokenLoaded:{
[session openWithCompletionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
//handle the updating of views according to the sate of session
}];
break;
I agree with JohnG, with the additional caveat of:
Note that if you have multiple cases inside of handleOpenURL:, you can filter for:
if ([sourceApplication isEqualToString:#"com.facebook.facebook"] ||
[sourceApplication isEqualToString:#"com.facebook.Facebook"]){
//Do Stuff
}
It's weird, but I was able to replicate on multiple devices the sourceApplication coming back as "Facebook" and "facebook".
On FB SDK 3.5, You can kill the token with this:
[[FBSessionTokenCachingStrategy defaultInstance] clearToken];