Question

I am using Facebook.Client for Windows Phone 8 in order to handle user login through Facebook on my game.

I was implementing the Facebook login feature using Facebook.Client.FacebookSessionClient.LoginWithApp(), however this always causes a redirection to one of my app's pages. I am using MonoGame/XNA to make the game, so my app contains only the game page where every part of the game is drawn into. When redirecting to it, I lose the "progress" of the game (as in the game restarts again in the main menu because of the redirection).

This behavior made me try using Facebook.Client.FacebookSessionClient.LoginAsync() (I still don't know what it does as I can't find it documented somewhere, but it if doesn't cause redirects, then it's what I need).

I'm currently trying to handle login using LoginAsync(), however it's throwing this exception:

System.UnauthorizedAccessException: Invalid cross-thread access.

And this is the code that I'm using (note that the try-catch statement is there in order to catch the exact exception, otherwise I'll just get a System.AggregateException):

FacebookSessionClient fb = new FacebookSessionClient(AppId);

Task<FacebookSession> fbst = null;
FacebookSession fbs = null;

try
{
    fbst = fb.LoginAsync("basic_info");
    fbs = fbst.Result;
}
catch (AggregateException e)
{
    Debug.WriteLine(e.ToString());
    Debug.WriteLine(e.Message);
}

What could be causing the Unauthorized Access exception? Also, if it's possible to use LoginWithApp() without redirecting (or any other form of login without redirection), that would do as well.

Was it helpful?

Solution

I managed to find the solution for this issue. It happens because apparently, when using MonoGame it is not possible to access Application.Current.RootVisual, thus throwing this exception.

As reported in page 438 of the Windows 8 and Windows Phone 8 Game Development book:

Windows Phone applications cannot interact with the XAML controls from within the game class code as the game code runs in a different thread that is not allowed to access UI components. To deal with this, the Dispatcher object is used to queue the updates for processing by the UI thread.

In Facebook.Client's code (available in their GitHub repo), there is a line in PhoneWebAuthentication.cs that does this:

PhoneApplicationFrame rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;

This is the line that causes the exception and disrupts the behavior of LoginAsync().

I have opened an issue in their GitHub page.

For now, if you want LoginAsync() to work in WP8 using MonoGame (it does not cause redirections, thus being exactly what I was looking for!), you will need to download the source code of Facebook.Client for Windows Phone 8 from the GitHub repo mentioned above and link it in your project. After that, make your AuthenticateAsync() function look like the one below:

public static Task<WebAuthenticationResult> AuthenticateAsync(WebAuthenticationOptions options, Uri startUri, Uri endUri)
{
    if (options != WebAuthenticationOptions.None)
    {
        throw new NotImplementedException("This method does not support authentication options other than 'None'.");
    }

    WebAuthenticationBroker.StartUri = startUri;
    WebAuthenticationBroker.EndUri = endUri;
    WebAuthenticationBroker.AuthenticationInProgress = true;

    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        (Application.Current.RootVisual as PhoneApplicationFrame).Navigate(new Uri("/Facebook.Client;component/loginpage.xaml", UriKind.Relative));
    });

    Task<WebAuthenticationResult> task = Task<WebAuthenticationResult>.Factory.StartNew(() =>
    {
        authenticateFinishedEvent.WaitOne();
        return new WebAuthenticationResult(responseData, responseStatus, responseErrorDetail);
    });

    return task;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top