Native Facebook app does not open with Facebook login in iOS 9

IosObjective CFacebookIos9Facebook Login

Ios Problem Overview


I have updated iPhone 6 plus to iOS 9 beta and trying to perform Facebook login but each time its presenting UIWebView with Facebook login form.

I have Facebook sdk

FB_IOS_SDK_VERSION_STRING @"3.24.0"
FB_IOS_SDK_TARGET_PLATFORM_VERSION @"v2.2"

And I am using following methods to perform Facebook Login

    NSArray *permissions = @[@"email",@"user_birthday",@"public_profile"];
    
    
     FBSessionStateHandler completionHandler = ^(FBSession *session, FBSessionState status, NSError *error) {
         [self sessionStateChanged:session state:status error:error];
     };
     
     if ([FBSession activeSession].state == FBSessionStateCreatedTokenLoaded) {
     // we have a cached token, so open the session
         [[FBSession activeSession]openWithBehavior:FBSessionLoginBehaviorUseSystemAccountIfPresent
                                 fromViewController:nil
                                  completionHandler:completionHandler];
     } else {
         
     [self clearAllUserInfo];
    [[NSURLCache sharedURLCache] removeAllCachedResponses];

     // create a new facebook session
     FBSession *fbSession = [[FBSession alloc] initWithPermissions:permissions];
     [FBSession setActiveSession:fbSession];
     [fbSession openWithBehavior:FBSessionLoginBehaviorUseSystemAccountIfPresent
              fromViewController:nil
               completionHandler:completionHandler];
     }

I have following setting under plist file

	<key>LSApplicationQueriesSchemes</key>
	<array>
		<string>fbapi</string>
		<string>fbapi20130214</string>
		<string>fbapi20130410</string>
		<string>fbapi20130702</string>
		<string>fbapi20131010</string>
		<string>fbapi20131219</string>
		<string>fbapi20140410</string>
		<string>fbapi20140116</string>
		<string>fbapi20150313</string>
		<string>fbapi20150629</string>
		<string>fb-messenger-api20140430</string>
		<string>fbauth</string>
		<string>fbauth2</string>
   <array>

Please let me know what I am missing here. First it is checking for iPhone device Setting-> Facebook credentials but never open Facebook app for login. Seems it does not recognize Facebook app installed on device.

Ios Solutions


Solution 1 - Ios

Below is complete process for new "Facebook login".


this is how I have revised my Facebook Login integration to get it work on latest update.

> Xcode 7.x , iOS 9 , Facebook SDK 4.x

Step-1. Download latest Facebook SDK (it includes major changes).

Step-2. Add FBSDKCoreKit.framework and FBSDKLoginKit.framework to your project.

Step-3. Now go to Project > Build Phases > add SafariServices.framework

Step-4. There are three changes in info.plist we need to verify.

4.1 Make sure you have below in your info.plist file

> CFBundleURLTypes > > > CFBundleURLSchemes > > > > > > FacebookAppID > > FacebookDisplayName >

4.2 Now add below for White-list Facebook Servers, this is must for iOS 9

> NSAppTransportSecurity > > NSExceptionDomains > > facebook.com > > NSIncludesSubdomains > > NSExceptionRequiresForwardSecrecy > > > fbcdn.net > > NSIncludesSubdomains > > NSExceptionRequiresForwardSecrecy > > > akamaihd.net > > NSIncludesSubdomains > > NSExceptionRequiresForwardSecrecy > > > >

4.3 Add URL schemes

> LSApplicationQueriesSchemes > > fbapi > fb-messenger-api > fbauth2 > fbshareextension >

Step-5. Now open AppDelegate.m file

5.1 Add below import statements, (remove old one).

> #import > #import

5.2 update following following methods

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                         openURL:url
                                               sourceApplication:sourceApplication
                                                      annotation:annotation];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
  [FBSDKAppEvents activateApp];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                    didFinishLaunchingWithOptions:launchOptions];
}

Step-6. Now we need to modify our Login Controller, where we do Login task

6.1 Add these imports in Login ViewController.m

> #import > #import

6.2 Add Facebook Login Button

FBSDKLoginButton *loginButton = [[FBSDKLoginButton alloc] init];
loginButton.center = self.view.center;
[self.view addSubview:loginButton];

6.3 Handle Login button click

-(IBAction)facebookLogin:(id)sender
{
    FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
    
    if ([FBSDKAccessToken currentAccessToken])
    {
        NSLog(@"Token is available : %@",[[FBSDKAccessToken currentAccessToken]tokenString]);
        [self fetchUserInfo];
    }
    else
    {
        [login logInWithReadPermissions:@[@"email"] fromViewController:self handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
         {
             if (error)
             {
                 NSLog(@"Login process error");
             }
             else if (result.isCancelled)
             {
                 NSLog(@"User cancelled login");
             }
             else
             {
                 NSLog(@"Login Success");
                 
                 if ([result.grantedPermissions containsObject:@"email"])
                 {
                     NSLog(@"result is:%@",result);
                     [self fetchUserInfo];
                 }
                 else
                 {
                     [SVProgressHUD showErrorWithStatus:@"Facebook email permission error"];

                 }
             }
         }];
    }
}

6.4 Get user info (name, email etc.)

-(void)fetchUserInfo
{
    if ([FBSDKAccessToken currentAccessToken])
    {
        NSLog(@"Token is available : %@",[[FBSDKAccessToken currentAccessToken]tokenString]);
        
        [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:@{@"fields": @"id, name, email"}]
         startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
             if (!error)
             {
                 NSLog(@"results:%@",result);
                 
                 NSString *email = [result objectForKey:@"email"];
                 NSString *userId = [result objectForKey:@"id"];
                 
                 if (email.length >0 )
                 {
                     //Start you app Todo
                 }
                 else
                 {
                 	NSLog(@“Facebook email is not verified");
                 }
             }
             else
             {
                 NSLog(@"Error %@",error);
            }
         }];
    }
}

Step-7. Now you can build project, you should get below screen.

enter image description here

Hope this will help you guys.

References : Thanks to Facebook docs, Stackoverflow posts and Google.

Solution 2 - Ios

This is by design. Facebook still have some issue with iOS9.

See the Facebook team answere : https://developers.facebook.com/bugs/786729821439894/?search_id Thanks

Solution 3 - Ios

In the end I changed my Podfile to previous FB version:
From:

pod 'FBSDKCoreKit' pod 'FBSDKLoginKit' pod 'FBSDKShareKit'
TO:

pod 'FBSDKCoreKit','~>4.5.1'
pod 'FBSDKLoginKit','~>4.5.1'
pod 'FBSDKShareKit','~>4.5.1'

From my point of view Facebook should check last login of the user and based on it trigger the correct Login flow.(and keep the small developers out of "web vs native war").

Solution 4 - Ios

@dan is right. In order to provide the best experience for users on iOS 9, the new SDK determines the best login flow automatically. If you're running on iOS 8 or earlier, the app switch will still be preferred.

Solution 5 - Ios

Safari View Controller is by default in the Facebook SDK. For those of you who want to revert to the previous experience, see below. It works only for 3.x SDK, this will not work on 4.x.

If you like to make the v3.x SDK (tested on v3.24.1) work like before (without opening Safari View Controller and make the app switch instead) call this code somewhere at the start of the app, e.g. didFinishLaunchingWithOptions:

SEL useSafariSel = sel_getUid("useSafariViewControllerForDialogName:");
SEL useNativeSel = sel_getUid("useNativeDialogForDialogName:");
Class FBDialogConfigClass = NSClassFromString(@"FBDialogConfig");

Method useSafariMethod = class_getClassMethod(FBDialogConfigClass, useSafariSel);
Method useNativeMethod = class_getClassMethod(FBDialogConfigClass, useNativeSel);

IMP returnNO = imp_implementationWithBlock(^BOOL(id me, id dialogName) {
    return NO;
});
method_setImplementation(useSafariMethod, returnNO);

IMP returnYES = imp_implementationWithBlock(^BOOL(id me, id dialogName) {
    return YES;
});
method_setImplementation(useNativeMethod, returnYES);

It swizzles two methods from FBDialogConfig.

Don't forget to import the objc/runtime.h header:

#import <objc/runtime.h>

@SimonCross some people just don't want to understand that Safari View Controller provides the best user experience - they think, or know for sure, that their users are not logged into Facebook in Safari, but are for sure logged in in the Facebook App.

Solution 6 - Ios

After setting all the necessary .plist keys as mentioned in this column, I used following solution to come out of login problem.

var fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.loginBehavior = FBSDKLoginBehavior.Web

So that it always logs in with in application.

Solution 7 - Ios

With the release of iOS 9, Apple introduced some significant changes to app switching. This has affected iOS 9 apps integrated with Facebook. Most people will notice this in their experience using Facebook Login. In apps that use the newest SDK (v4.6 and v3.24), we will surface a flow using Safari View Controller (SVC) instead of fast-app-switching (FAS) because of additional dialog interstitials that add extra steps to the login process in FAS on iOS 9. Additionally, data that we've seen from more than 250 apps indicate that this is the best experience for people in the long run. Please read on for details. https://developers.facebook.com/blog/post/2015/10/29/Facebook-Login-iOS9

Solution 8 - Ios

Facebook has changed Facebook login behavior for iOS9.

Here is the quote from Facebook blog post:

> We've been monitoring data and CTRs for over 250 apps over the last 6 weeks since iOS 9 launched. The click-through rate (CTR) of SVC Login outperforms the CTR of app-switch Login and is improving at 3x the rate of the app-switch experience. This indicates that the SVC experience is better for people and developers today, and will likely be the best solution in the long run. For this reason, the latest Facebook SDK for iOS uses SVC as the default experience for Login.

Solution 9 - Ios

This worked for me. Add this to your .plist.

<key>LSApplicationQueriesSchemes</key>
	<array>
        <string>fb</string>
    </array>

For iOS9, we need to add key to our .plist for URL Schemes.

Solution 10 - Ios

I know it is old. But you can put this code to your application:(UIApplication *)application didFinishLaunchingWithOptions:

SEL useNativeSel = sel_getUid("useNativeDialogForDialogName:");
Class FBSDKServerConfiguration = NSClassFromString(@"FBSDKServerConfiguration");


Method useNativeMethod = class_getInstanceMethod(FBSDKServerConfiguration, useNativeSel);

IMP returnYES = imp_implementationWithBlock(^BOOL(id me, id dialogName) {
    return YES;
});
method_setImplementation(useNativeMethod, returnYES);

And FacebookSDK will login through native app when app installed instead of browser.

Solution 11 - Ios

Putting this one in appdelegate solved my problem

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
    }

Solution 12 - Ios

Adding below lines to .plist file helped me:

<key>LSApplicationQueriesSchemes</key> 
    <array>
      <string>fbapi</string>
      <string>fbapi20130214</string>
      <string>fbapi20130410</string>
      <string>fbapi20130702</string>
      <string>fbapi20131010</string>
      <string>fbapi20131219</string>
      <string>fbapi20140410</string>
      <string>fbapi20140116</string>
      <string>fbapi20150313</string>
      <string>fbapi20150629</string>
      <string>fbauth</string>
      <string>fbauth2</string>
      <string>fb-messenger-api20140430</string>
    </array>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBhumeshwer katreView Question on Stackoverflow
Solution 1 - IosswiftBoyView Answer on Stackoverflow
Solution 2 - Iosuser3492452View Answer on Stackoverflow
Solution 3 - IosMike.RView Answer on Stackoverflow
Solution 4 - IosChris PanView Answer on Stackoverflow
Solution 5 - IosAndrei RadulescuView Answer on Stackoverflow
Solution 6 - Iosuser5503563View Answer on Stackoverflow
Solution 7 - IosVenu Gopal TewariView Answer on Stackoverflow
Solution 8 - IosHaroun SMIDAView Answer on Stackoverflow
Solution 9 - IosSushil SharmaView Answer on Stackoverflow
Solution 10 - Iosvien vuView Answer on Stackoverflow
Solution 11 - IosChanchal RajView Answer on Stackoverflow
Solution 12 - IosSai KumarView Answer on Stackoverflow