Xamarin.Auth Native Code Change Application class on iOS and can't change Application.Current.MainPg

DrutDrut USMember

Hello,
Im using Xamarin.Auth to get user token for Facebook...
In Android all good! But in iOS Im facing a little problem...
Here is my code:

Custom renderer in iOS:

using System;
using Xamarin.Auth;
using Xamarin.Forms.Platform.iOS;
using Xamarin.Forms;
using App;
using App.iOS;
using UIKit;

[assembly: ExportRenderer (typeof (FacebookPage), typeof (FacebookPageRenderer))]

namespace App.iOS
{
    public class FacebookPageRenderer : PageRenderer
    {

        bool IsShown;

        public override async void ViewDidAppear (bool animated)
        {
            base.ViewDidAppear (animated);

            if( ! IsShown ) {

                IsShown = true;

                var auth = new OAuth2Authenticator (
                    clientId: "0000000_FakeId", // your OAuth2 client id
                    scope: "", // The scopes for the particular API you're accessing. The format for this will vary by API.
                    authorizeUrl: new Uri ("https://m.facebook.com/dialog/oauth/"), // the auth URL for the service
                    redirectUrl: new Uri ("https://www.facebook.com/connect/login_success.html")); // the redirect URL for the service

                auth.Completed += async (sender, eventArgs) => {

                    if (eventArgs.IsAuthenticated) {
                        // Use eventArgs.Account to do wonderful things

                        await DismissViewControllerAsync(true);
                        App.Instance.SaveToken(eventArgs.Account.Properties["access_token"]);

                    } else {
                        DismissViewControllerAsync(true);
                        App.Instance.CancelFBLoginAction();
                    }
                };

                PresentViewController (auth.GetUI (), true, null);
            }
        }
    }
}

Here is my Facebook Shared Page:

using System;
using System.Collections.Generic;
using Xamarin.Forms;

namespace App
{
    public class FacebookPage : ContentPage
    {
        public FacebookPage ()
        {
            NavigationPage.SetHasNavigationBar (this, false);

            MessagingCenter.Subscribe<App> (this, "Pop", (sender) => {
                Navigation.PopAsync();

                MessagingCenter.Unsubscribe<App> (this, "Pop");
                MessagingCenter.Unsubscribe<App> (this, "Authenticated");
            });

            MessagingCenter.Subscribe<App> (this, "Authenticated",(sender) => {
                MessagingCenter.Unsubscribe<App> (this, "Pop");
                MessagingCenter.Unsubscribe<App> (this, "Authenticated");

                Navigation.PopAsync();
                    Navigation.PushAsync(new OtherPage());
            });
        }

Here is some code from my App.cs Page:

                string _Token;
        public string Token {

            get { return _Token; }
        }

        public void SaveToken(string token)
        {
            _Token = token;

            //Save token...

            // broadcast a message that authentication was successful
            MessagingCenter.Send<App> (this, "Authenticated");
        }

        public void CancelFBLoginAction()
        {
            MessagingCenter.Send<App> (this, "Pop");

        }

And here is some code from my MainPage, which I use for Login:

                FbButton = new Button
                {
                    Text = "FB",
                    BorderRadius = 5,
                    FontSize = 20,
                    TextColor = Color.Wh
                };

                FbButton.Clicked += async (sender, e) => {
                    await Navigation.PushAsync(new FacebookPage());
                };

                               loginButton = new Button
                {
                    Text = "Login",
                    BorderRadius = 5,
                    FontSize = 20,
                    TextColor = Color.Black,
                };

                loginButton.Clicked += async (sender, e) => {
                                //Some checks omitted

                if (Login == true) {
                                        var profileNav =new MainPage();
                        Application.Current.MainPage = profileNav;

                    }
                };

Okay.... My app flow is:
- User login normally go to main page just fine!
-User uses Facebook, FacebookPage is prompt and a native page is shown with Xamarin.Auth...
***-User cancel the action... I dismiss the ControllerView, Send a Pop Message and go back to Login Page. Once there, my user can't do normal login anymore, because seems that the Application class has been changed. If my user try login... when I set Application.Current.MainPage = profileNav; nothing happens, because seems like it is changing another instance of Application and not the one that has the LoginPage. Im not sure if what Im talking is correct. But it is what I think!
***-User is authenticated... I dismiss the ControllerView, Send a Authenticate message to Pop the FacebookPage, and return to LoginPage...where push to OtherPage where I try also to change Application.Current.MainPage, that don't work either.

Seems like when the FacebookPage use the Native Code from Xamarin.Auth the Application.Current changes and Facebook get the control.... When I dismiss the ViewController the Facebook still has the control on Application.Current... I confirmed that because the Application.Current.Id changes after I call FacebookPage. On Android all working perfect! How could I solve this? Or what is the real problem? (not sure if what I said about Control is right).

I can't change Application.Current.MainPage after using the FacebookPageRenderer

Posts

  • DrutDrut USMember

    Found a very similar topic... without answer either

    Some help?

  • DrutDrut USMember

    Hi just find a "kind of workaround" for this...

    If I use this code for set the current main page after use the FacebookPageRenderer... it ends up working.
    However if I do not use the renderer... when using the normal loging flow... it doesn't work!

            #if __IOS__
            App.Instance.MainPage = profileNav;
                await UIKit.UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewControllerAsync( App.Instance.MainPage.CreateViewController(),true);
                #endif
    

    So this don't fixed my problem...
    But again confirmed the "suspect" that FacebookViewController was still in Control even after Dismissing it.

  • DrutDrut USMember
    edited July 2015

    Hello,

    I think the problem may be here... In my App.cs I have this code:

            static volatile App _Instance;
            static object _SyncRoot = new Object();
            public static App Instance {
                get {
                    if (_Instance == null) {
                        lock (_SyncRoot) {
                            if (_Instance == null) {
                                _Instance = new App ();
                            }
                        }
                    }
    
                    return _Instance;
                }
    
            }
    

    And every first time I call App.Instance like I do in App.Instance.CancelFBLoginAction(); .... The _Instance is null and it return a new App Class...

    This code I got from here:

    Here is the GitSource

    As Sauve says in Git, this code is:
    // just a singleton pattern so I can have the concept of an app instance

    Maybe this is what is causing my problem...
    Will try to remove this Instance property and try.
    If anyone could help in a work around so I could not dele this property would be good

Sign In or Register to comment.