Xamarin.Forms - Facebook Login : Native login page (Android)

Hello,
Initially i tried to use this library https://github.com/jsauve/OAuthTwoDemo.XForms/ but the problem was that the Library opened a WebView with mobile Facebook Login, and the user was forced to insert every time facebook username and password.

Instead with my solution my app open native facebook login page and if can't find Facebook App installed on device, it open a WebView.

Android Project Reference:

Xamarin Project Reference:

Xamarin.Forms Project:
Create Custom Button

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace MyApp.CustomControls
{
    public class FacebookLoginButton : Button
    {

    }
}

Create Login Page (XAML)

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:customcontrols="clr-namespace:MyApp.CustomControls;assembly=MyApp"
             x:Class="MyApp.LoginPage" BackgroundColor="White">
        <StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Padding="15">
                <customcontrols:FacebookLoginButton Text="Login With Facebook" VerticalOptions="Start" 
                HorizontalOptions="FillAndExpand"></customcontrols:FacebookLoginButton>
        </StackLayout>
</ContentPage>

Xamarin.Android Project:
Create Custom Button Renderer

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Acr.XamForms.UserDialogs;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using MyApp.CustomControls;
using MyApp.Droid.Utils;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(FacebookLoginButton), typeof(FacebookLoginButtonRenderer))]
namespace MyApp.Droid.Utils
{
    public class FacebookLoginButtonRenderer : ButtonRenderer
    {
        public Xamarin.Forms.Button formsButton;
        private readonly IUserDialogService _dialogService;

        public FacebookLoginButtonRenderer()
            : base()
        {
            this._dialogService = DependencyService.Get<IUserDialogService>();
        }
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement != null)
            {
                formsButton = e.NewElement;
            }
            if (this.Control != null)
            {
                global::Android.Widget.Button button = this.Control;
                button.Click += button_Click;
            }
        }

        void button_Click(object sender, EventArgs e)
        {
            var activity = this.Context as Activity;
            var intent = new Intent(activity, typeof(LoginActivity));

            Forms.Context.StartActivity(intent);
            formsButton.Navigation.PopModalAsync();
        }
    }
}

Create LoginActivity

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Acr.XamForms.UserDialogs;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using MyApp.Services;
using Xamarin.Facebook;
using Xamarin.Forms;
//IMPORTANT You MUST define "app_id" in Strings.xml
[assembly: MetaData("com.facebook.sdk.ApplicationId", Value = "@string/app_id")]
namespace MyApp.Droid
{
    [Activity(Label = "LoginActivity")]
    public class LoginActivity : Activity, Session.IStatusCallback, Request.IGraphUserCallback
    {
        private readonly IUserDialogService _dialogService;
        public LoginActivity()
            : base()
        {
            this._dialogService = DependencyService.Get<IUserDialogService>();
        }
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            OpenFacebookSession();
        }

        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);

            // Relay the result to our FB Session
            Session.ActiveSession.OnActivityResult(this, requestCode, (int)resultCode, data);
        }

        public void Call(Session session, SessionState state, Java.Lang.Exception exception)
        {
            // Make a request for 'Me' information about the current user
            if (session.IsOpened)
                Request.ExecuteMeRequestAsync(session, this);
        }

        public async void OnCompleted(Xamarin.Facebook.Model.IGraphUser user, Response response)
        {
            // 'Me' request callback
            if (user != null) {

                string fb_id = user.Id;
                string fb_email = user.InnerJSONObject.Get("email").ToString();
                string fb_firstName = user.FirstName;
                string fb_lastName = user.LastName;
                string message = String.Format("{0} {1}. FacebookID: {2}. Email: {3}", fb_firstName, fb_lastName, fb_id, fb_email);
                this._dialogService.Alert(message);
                Console.WriteLine(message);
            }
            else
            {
                string message = "Problem during Facebook Login!");
                this._dialogService.Alert(message);
                Console.WriteLine(message);
            }
            OnBackPressed(); 
        }

        public void OpenFacebookSession()
        {
            // Ask for username and password
            Xamarin.Facebook.Session.OpenRequest op = new Session.OpenRequest(this);
            //op.SetLoginBehavior(SessionLoginBehavior.SsoWithFallback);
            op.SetCallback(this);

            List<String> permissions = new List<String>();
            //permissions.Add("publish_stream");
            //permissions.Add("user_likes");
            permissions.Add("email");
            //permissions.Add("user_birthday");
            //permissions.Add("publish_actions");
            //permissions.Add("share_item");
            //permissions.Add("user_friends");
            //permissions.Add("user_groups");

            op.SetPermissions(permissions);

            Session session2 = new Xamarin.Facebook.Session.Builder(this).Build();
            Session.ActiveSession = session2;
            session2.OpenForPublish(op);
        }
    }
}

That's all!

Please contact me if you have suggestion!

Esteban Lombardo
.NET Developer
Logica S.r.l.

«1

Posts

  • Bord1986.6225Bord1986.6225 ITMember ✭✭

    Could please provide a sample project?

  • IdoTeneIdoTene USMember, University ✭✭

    Hi,

    I've created a similar project for Facebook integration for xamarin forms (works for iOS & Android):
    https://github.com/IdoTene/XamarinFormsNativeFacebook

  • Great @IdoT !!! I found a solution also for iOS but now i cannot post the solution because of a lot of job!!!

  • @IdoT Hey! your solution was great.
    I have a question though... how would I add permission on FBSession.ActiveSession.Open I was unable to find an answer.
    Thanks in advanced

  • AlejandroForondaAlejandroForonda BOMember
    edited March 2015

    Nevermind I was looking on the wrong side of the internet, that's why I didn't find an answer.

    For iOS
    You have to call FBSession.OpenActiveSession insted of FBSession.ActiveSession.Open() on the FacebookLoginButtonRenderer.cs

    FBSession.OpenActiveSession(permissions , true, (aSesion, status, error) => { ...

    Where "permissions" is just a string[] array

    For Android
    You call the same function

    Session.OpenActiveSession(this, true, permissions, this);

    just add permissions parameter that is a IList whit the permissions you desire (this is on FacebookActivity.cs)

  • IdoTeneIdoTene USMember, University ✭✭

    Thanks @AlejandroForonda, I'll check this fix later on!

  • IdoTeneIdoTene USMember, University ✭✭

    @AlejandroForonda - I tried to change the code to what you have posted, but in this way, if there is a built in account, you still see a pop up from safari, rather then using the built in account:
    FBSession.ActiveSession.Open(FBSessionLoginBehavior.UseSystemAccountIfPresent ..)
    How do you specify the FBSessionLoginBehavior.UseSystemAccountIfPresent ?

  • for me it opens the facebook app not safari. It opens safari if you don't have facebook installed....
    But I think I'm not uunderstanding the question

  • iturraldepabloiturraldepablo ESMember

    Hi @IdoTene ,

    really hope you can help me I have review your code githug project a looks great, but Im having lots of problems with the xamarin.android.support library it doesn't find the session clases. Can you please advice me,

    Compiler errors -> click me

    I have the package but the clases are no find

  • VilleKangasVilleKangas FIMember

    @iturraldepablo , I'm having the same problem. The app works fine on iOS after I added LoadApplication(new App()); to FinishedLaunching method on AppDelegate.cs. But on Android the Session class could not be found and I haven't figured out how to fix that yet. If you find a solution, please let me know.

  • IdoTeneIdoTene USMember, University ✭✭

    hi @iturraldepablo & @vkang , I'm happy to hear you are using my component!
    Regarding the compilation errors in android, I'm using an old version of Facebook SDK.
    I wrote it about 3 months ago, yet the new sdk totally not supporting the old code :(

    Until I'll upgrade to the new sdk, you can manually take the old version (4.1.2.0)

  • VilleKangasVilleKangas FIMember

    Thanks @IdoTene , for some reason all the packages and stuff were messed up Visual Studio, so I switched to Xamarin Studio and installed an older version of the Facebook Android SDK. With version 3.17.2.0 it started working. Now it works in Visual Studio, too.

  • IdoTeneIdoTene USMember, University ✭✭

    Great! I'm glad to hear it works!

  • Bord1986Bord1986 USMember

    Hi @IdoTene, do you have any advices about how to update to the new FB sdk?

  • IdoTeneIdoTene USMember, University ✭✭

    @Bord1986 - still haven't looked in the new SDK, so I have no clue..
    I hope to upgrade soon, when I'll do so, I'll update here in this discussion.

  • mikescandymikescandy ITBeta, University ✭✭
    edited August 2015

    Hey, I published an updated fork of @IdoTene 's code using the latest sdk. so far there's only Android, and I'm exposing the sdk login button, not the login manager, but you should get an idea.

    find it at https://github.com/mikescandy/XamarinFormsNativeFacebook

    /cc @Bord1986

  • iturraldepabloiturraldepablo ESMember
    edited August 2015

    Hi @mikescandy ,

    Check your repository and works really well.

    if anyone can help me, Im trying to share a link with Facebook but I can not finishing finding my way out, this is my code is on element change of a render button:

    [assembly: ExportRenderer(typeof(FacebookPostButton), typeof(FacebookPostButtonRendererAndroid))]
    namespace XX.Droid
    {
    
        public class FacebookPostButtonRendererAndroid : ViewRenderer<Button, LoginButton>
        {
    
            protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
            {
                base.OnElementChanged (e);
    
                var callbackManager = CallbackManagerFactory.Create();
    
                ShareDialog shareDialog = new ShareDialog (this.Context);
    
    
                shareDialog.RegisterCallback (callbackManager, new FacebookCallback<SharerResult> () {
                    HandleSuccess = shareResult => {
                        Action<string> local = App.PostSuccessFacebookAction;
                        if (local != null) {
                            local (shareResult.PostId);
                        }
                    },
                    HandleCancel = () => {
                        Console.WriteLine ("HelloFacebook: Canceled");
                    },
                    HandleError = shareError => {
                        Console.WriteLine ("HelloFacebook: Error: {0}", shareError);
                    }
                });
    
                ShareLinkContent.Builder content = new ShareLinkContent.Builder ();
                content.SetContentUrl(Android.Net.Uri.Parse("https://developers.facebook.com"));
                ShareLinkContent shareContent  = content.Build ();
    
                shareDialog.Show (shareContent);
            }
        }
    }
    

    I have errors with ShareDialog shareDialog = new ShareDialog (this.Context); it tell me

    ** Argument #1' cannot convertAndroid.Content.Context' expression to type `Android.Support.V4.App.Fragment' **

    Any Idea idea how can i solve this??

  • @mikescandy Im trying to use your code. But for some reason every time I try to use FacebookLoginButton I get this error:

    [AndroidRuntime] FATAL EXCEPTION: AsyncTask #4
    [AndroidRuntime] java.lang.NullPointerException
    [AndroidRuntime]    at java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:781)
    [AndroidRuntime]    at com.facebook.internal.Utility.queryAppSettings(Utility.java:825)
    [AndroidRuntime]    at com.facebook.login.widget.LoginButton$1.run(LoginButton.java:489)
    [AndroidRuntime]    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
    [AndroidRuntime]    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
    [AndroidRuntime]    at java.lang.Thread.run(Thread.java:856)
    

    Have already tried to generate a new Hash also... but no luck...
    It works on your example...
    But in my project don`t.
    Im having a hard time to solve this...
    Any change you know what is the problem?

  • If anyone is having the same problem I solve it with this

    Just add this line inside you application div in manifest file:

    <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/app_id"/>

    you will have something like this:

    <application  android:icon="@drawable/icon" >
        <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/app_id"/>
            <activity android:name="com.facebook.LoginActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:label="@string/app_name" />
            <activity android:name="com.facebook.FacebookActivity"
              android:configChanges=
                "keyboard|keyboardHidden|screenLayout|screenSize|orientation"
              android:theme="@android:style/Theme.Translucent.NoTitleBar"
              android:label="@string/app_name" />
        </application>
    

    This solved my problem!!

    Had a hard time fixing it :)

    Hope it helps

  • KeyvanVakiliKeyvanVakili USMember

    Hi @mikescandy. Thanks for sharing the code. I've managed to run the code but when I use the button I get the following error message within the app:
    "Given URL is not allowed by the Application configuration: One or more of the given URLs is not allowed by the App's settings. To use this URL you must add a valid native platform in your App's settings."
    I'm not quite sure what I should do to fix the problem (and I'm quite new to the whole Android programming). Any help is much appreciated.

  • vinodkumarvinodkumar INMember ✭✭

    @IdoTene said:
    Hi,

    I've created a similar project for Facebook integration for xamarin forms (works for iOS & Android):
    https://github.com/IdoTene/XamarinFormsNativeFacebook

    Hi @IdoTene
    I am getting an error while building the project.

    I have downloaded your project and restored all the packages and tried to build the solution. Below is the error which I am getting. Please help.

    Error Unexpected error - Please file a bug report at http://bugzilla.xamarin.com. Reason: System.IO.DirectoryNotFoundException: Could not find a part of the path "Downloads\XamarinFormsNativeFacebook-master\XamarinFormsNativeFacebook-master\XamarinNativeFacebook\XamarinNativeFacebook.Droid\obj\Debug__library_projects__\Xamarin.Facebook\library_project_imports\res\drawable\com_facebook_button_background.xml" XamarinNativeFacebook.Droid

  • Josu_brJosu_br USMember ✭✭

    @vinodkumar said:

    @IdoTene said:
    Hi,

    I've created a similar project for Facebook integration for xamarin forms (works for iOS & Android):
    https://github.com/IdoTene/XamarinFormsNativeFacebook


    Hi @IdoTene
    I am getting an error while building the project.

    I have downloaded your project and restored all the packages and tried to build the solution. Below is the error which I am getting. Please help.

    Error Unexpected error - Please file a bug report at http://bugzilla.xamarin.com. Reason: System.IO.DirectoryNotFoundException: Could not find a part of the path "Downloads\XamarinFormsNativeFacebook-master\XamarinFormsNativeFacebook-master\XamarinNativeFacebook\XamarinNativeFacebook.Droid\obj\Debug__library_projects__\Xamarin.Facebook\library_project_imports\res\drawable\com_facebook_button_background.xml" XamarinNativeFacebook.Droid

    try change your root directory, because your current directory name is too long, a suggest you change it to "C:\YOUR_PROJECT_NAME".

  • Mohamed.3628Mohamed.3628 USMember
    edited May 2016

    I get this error:

    **No resource found that matches the given name: attr 'android:elevation'.
    **XamarinNativeFacebook.Droid C:\Users.....\XamarinNativeFacebook.Droid\obj\Debug\resourcecache\49D683CCA49A2310CBA9AB8BDBF331FB\res\values\values.xml

  • Rex232Rex232 USMember ✭✭

    It > @mikescandy said:

    Hey, I published an updated fork of @IdoTene 's code using the latest sdk. so far there's only Android, and I'm exposing the sdk login button, not the login manager, but you should get an idea.

    find it at https://github.com/mikescandy/XamarinFormsNativeFacebook

    /cc @Bord1986

    Hi mikescandy, I just download it and work fine. however, ios still pop webview even i have installed fb, any idea ?

  • mikescandymikescandy ITBeta, University ✭✭

    not sure, haven't used that code in a while. Will have a look and see if I can sort it out.

  • @mikescandy Congratulations.

    I'm using your solution to sign in with facebook.
    https://github.com/mikescandy/XamarinFormsNativeFacebook

    This is all ok, now I need a way to retrieve the token saved at the app startup.

    How can I read the token that was recorded?

    Thank you so much.

  • AhirAhir USMember ✭✭

    Any solution for OAuth Google without webviews

  • HaskellHaskell MXMember ✭✭

    This only works for android, I want to do this for Cross Platforms, is this possible? (IOS and Android)

  • hvaughanhvaughan USMember ✭✭✭

    @Haskell

    You implement the code in your native projects but then you call the native code from your Forms PCL project. Look at the various links in this thread for examples of people who implemented it using Xamarin Forms PCL.

  • BrandonBestBrandonBest USMember ✭✭

    @GeraldoNevesdosSantos

    Does the native Facebook login work for both iOS and Android?
    Also did you find a way to grab to user token?

  • EmreAltanEmreAltan USMember ✭✭

    @mikescandy said:
    Hey, I published an updated fork of @IdoTene 's code using the latest sdk. so far there's only Android, and I'm exposing the sdk login button, not the login manager, but you should get an idea.

    find it at https://github.com/mikescandy/XamarinFormsNativeFacebook

    Hi @mikescandy ,
    Getting following error when I try to build your solution:
    'The file "obj\Debug\android\bin\packaged_resources" does not exist.'

    Any suggestion?

  • mikescandymikescandy ITBeta, University ✭✭

    @EmreAltan sorry, no idea. just checked out and compiled fine. doesn-t seem to do a lot , but compiles and starts. try to clean bin and obj folders and try again.

  • EmreAltanEmreAltan USMember ✭✭

    @mikescandy Sorry, my fault :) Strange but it happened when I loaded Android 7.0 on SDK Manager. I've uninstalled it and problem has solved for now. Now I'm trying to change the login button's style. But it's not easy to do inside of "FacebookLoginButtonRendererAndroid" class. Do you have any suggestion?

    Besides, the original button looks like this:

    I'm using Xamarin.Facebook.Android v4.11.0.1 (Because of my target android framework which is 6.0)

  • mikescandymikescandy ITBeta, University ✭✭

    My Xamarin Forms skills are a bit rusty right now, but (according to https://stackoverflow.com/questions/16314651/customize-android-facebook-login-button) you should use the LoginManager.

    Try editing your renderer to something like this (disclaimer: there's probably a better way!)

    public class FacebookLoginButtonRendererAndroid : ViewRenderer<Button, Android.Widget.Button> 
    {
        private static Activity _activity;
        protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
        {
            base.OnElementChanged(e);
            _activity = this.Context as MainActivity;
            var loginButton = new Android.Widget.Button(this.Context);
    
            loginButton.Click += LoginButton_Click;
    
            base.SetNativeControl(loginButton);
        }
    
        private void LoginButton_Click(object sender, EventArgs e)
        {
            LoginManager.Instance.LogInWithReadPermissions((Activity)this.Context, new []{"public_profile", "user_friends"});
        }
    }
    

    and register the callback in the MainActivity.OnCreate (right after forms init) like this:

      var facebookCallback = new FacebookCallback<LoginResult>
                {
                    HandleSuccess = shareResult =>
                    {
                        Action<string> local = App.PostSuccessFacebookAction;
                        if (local != null)
                        {
                            local(shareResult.AccessToken.Token);
                        }
                    }
                    ,
                    HandleCancel = () =>
                    {
                        Console.WriteLine("HelloFacebook: Canceled");
                    },
                    HandleError = shareError =>
                    {
                        Console.WriteLine("HelloFacebook: Error: {0}", shareError);
                    }
                };
    
            LoginManager.Instance.RegisterCallback(MainActivity.CallbackManager, facebookCallback);
    

    as usual, works on my machine!

  • EmreAltanEmreAltan USMember ✭✭

    @mikescandy Thanks for help! I haven't tried your code, I've achieved this with a tricky way:

    `public class FacebookLoginButtonRenderer : ButtonRenderer
    {
    private static Activity _activity;
    LoginButton loginButton;

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
        {
            base.OnElementChanged(e);
            _activity = this.Context as MainActivity;
            loginButton = new LoginButton(this.Context);
            loginButton.Visibility = ViewStates.Gone;
    
            var facebookCallback = new FacebookCallback<LoginResult>
            {
                HandleSuccess = shareResult => {
                    Action<string> local = App.PostSuccessFacebookAction;
                    if (local != null)
                    {
                        Console.WriteLine("HelloFacebook: Success");
                        local(shareResult.AccessToken.Token);
                    }
                }
        ,
                HandleCancel = () => {
                    Console.WriteLine("HelloFacebook: Canceled");
                },
                HandleError = shareError => {
                    Console.WriteLine("HelloFacebook: Error: {0}", shareError);
                }
            };
    
            loginButton.RegisterCallback(MainActivity.CallbackManager, facebookCallback);
    
            Control.Click += Control_Click;
        }
    
        private void Control_Click(object sender, EventArgs e)
        {
            loginButton.PerformClick();
        }
    }`
    

    I wrote a simple ButtonRenderer and created an invisible Facebook's LoginButton inside of it. Then performed login button click when clicked the actual button.

    Now it's time to make Google authentication. Authentication is a real headache in Xamarin I think. Anyways, thank you again!

  • phknupphknup BRMember ✭✭

    @KeyvanVakili said:
    Hi @mikescandy. Thanks for sharing the code. I've managed to run the code but when I use the button I get the following error message within the app:
    "Given URL is not allowed by the Application configuration: One or more of the given URLs is not allowed by the App's settings. To use this URL you must add a valid native platform in your App's settings."
    I'm not quite sure what I should do to fix the problem (and I'm quite new to the whole Android programming). Any help is much appreciated.

    I'm having the same issue.

    :confused:

  • phknupphknup BRMember ✭✭
    edited August 2017

    Finally I got it! Thank you guys!

  • Arunkumar_XamArunkumar_Xam USMember ✭✭

    I get this error:
    how to solve it

  • is this still working? Xamarin.Facebook nuget pacakeg hasnt been updated for 2 years. facebook doesnt have sessions anymore

  • batmacibatmaci DEMember ✭✭✭✭✭

    @ChristopherDrosos said:
    is this still working? Xamarin.Facebook nuget pacakeg hasnt been updated for 2 years. facebook doesnt have sessions anymore

    xamarin.facebook.android was updated recently. what is the difference between these 3 anyway? is there a uwp optiona also?

Sign In or Register to comment.