When integrating facebook into our Xamarin mobile apps it could be painful, specially when we want to give the best UX by using facebook native apis instead of OAuth2 (which we know is not a very good experience to give to our users). That’s why after spending many hours trying to make facebook work in multiple applications, decided to remove this known frustration and created a plugin to abstract facebook api into a common interface that we can use the same way for Android and iOS.
This plugin makes it easier to use and integrate facebook (login,sharing and graph requests) on our applications. Also documented all the steps for achieving a Facebook succesful setup which I will be sharing here. So let’s go step by step.
General Setup
1 – Follow the steps on the facebook portal setup documentation here:
Creating a Facebook Application
2 – Install the plugin in all your projects:
Let’s Setup Android
1 – On you MainActivity class:
- Inside OnCreate method just after calling base.OnCreate add this call:
FacebookClientManager.Initialize(this);
- Override OnActivityResult:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
base.OnActivityResult(requestCode, resultCode, intent);
FacebookClientManager.OnActivityResult(requestCode, resultCode, intent);
}
2 – Create some string resources for facebook configuration (Resources/values/strings.xml)
<string name="facebook_app_name">MyFacebookAppName</string>
<string name="facebook_app_id">xxxxxxxxxxxxx</string>
<string name="fb_login_protocol_scheme">fbxxxxxxxxxxxxx</string>
Note: Replace xxxxxxxxxxxxx with your facebook app id.
3 – On your AndroidManifest.xml:
- Add this permission:
<uses-permission android:name="android.permission.INTERNET"/>
- Add this inside the application tag
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/facebook_app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
Let’s Setup iOS:
1 – On your AppDelegate class:
- Inside FinishedLaunching method just before return base.FinishedLaunching(app, options) add this call:
FacebookClientManager.Initialize(app,options);
- Override OnActivated(UIApplication uiApplication):
FacebookClientManager.OnActivated();
- Override OpenUrl methods
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
return FacebookClientManager.OpenUrl(app, url, options);
}
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return FacebookClientManager.OpenUrl(application, url, sourceApplication, annotation);
}
2 – On you Info.plist:
- Need to whitelist Facebook domains in your app by adding the following to your application’s Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>facebook.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>fbcdn.net</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>akamaihd.net</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
- Make sure you add any other additional urls for web services call inside the NSExceptionDomains dict too:
<key>otherExternalDomainYouNeedToCall</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
- Add the bundle url types for Facebook:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>fb</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fbxxxxxxxxxxxxx</string>
</array>
</dict>
</array>
<key>FacebookAppID</key>
<string>xxxxxxxxxxxxx</string>
<key>FacebookDisplayName</key>
<string>[Facebook app name]</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fbapi</string>
<string>fb-messenger-api</string>
<string>fbauth2</string>
<string>fbshareextension</string>
</array>
Note: Replace xxxxxxxxxxxxx with your facebook app id
- If your app needs access to the gallery because will be posting photos, remember to add the photo library permission.
<key>NSPhotoLibraryUsageDescription</key>
<string>{human-readable reason for photo access}</string>
3 – On your Entitlement.plist add:
<key>keychain-access-groups</key>
<array>
<string>{your-apple-app-id-prefix}.{your-apple-app-id-bundle-identifier}</string>
</array>
Ready to use
That was a lot of application setup, but we are finally done with it. Let’s go now on how to use it.
Authentication
To authenticate using facebook you just need to call LoginAsync method with the needed permissions.
FacebookResponse<bool> response = await CrossFacebookClient.Current.LoginAsync(new string[] {"email","public_profile"});
Login with read permissions & get user data
await CrossFacebookClient.Current.RequestUserDataAsync(new string[] { "email", "first_name", "gender", "last_name", "birthday" }, new string[] { "email", "user_birthday" });
Note: This method will check if has the requested permissions granted, if so will just get the user data. If not granted will prompt login requesting the missing permissions and after granted will get the user data.
Sharing
To share a photo you can do it by using ShareAsync method. You can share photos, videos or links.
FacebookSharePhoto[] photos = new FacebookSharePhoto[] { new FacebookSharePhoto(text, image) };
FacebookSharePhotoContent photoContent = new FacebookSharePhotoContent(photos);
await CrossFacebookClient.Current.ShareAsync(photoContent);
More on sharing content here:
Facebook Graph Requests
Plugin support doing graph requests by using:
- QueryDataAsync – Request information from faceboo
//Get all my likes
await CrossFacebookClient.Current.QueryDataAsync("me/likes", new string[]{ "user_likes"});
More on graph requests here:
Roadmap
There is still some work to do:
- UWP support
- Facebook Invites
- Facebook Analytics
You can find the full source code, sample and documentation here:
https://github.com/CrossGeeks/FacebookClientPlugin
Here is another great article about facebook native integration in Xamarin:
https://causerexception.com/2017/10/21/facebook-native-login-with-xamarin-forms/
Happy facebook integration!
2 Comments
Hello,
Thanks for this awesome plugin. Saved me a lot of time as I was going to rewrite what you did :).
One question : When a device already has FB app installed and logged In account , there is no activity that asks user to choose its account or to change for another one than the one which is actually loggedIn . Is this a normal behavior ?
Regards.
Hello Rendy, it works perfectly for me. There is some possibility that the profile image is larger. Now get it 50×50 px (data[“picture”][“data”][“url”] …. &height=50&width=50)
Try replacing the obtained values, but it does not work.
Comments are closed.