Saturday, February 11, 2017

Xamarin.Forms Android Facebook native SDK login with Azure

There are many scattered bits and pieces of tips for getting Facebook login working on the Xamarin.Forms platform, but none seem to quite cover the topic fully. This post will hopefully help someone out in getting everything put together in the right order.  For now, this post will only cover Android and the PCL project; a later post will touch on iOS.

This tutorial is aimed at people using the Azure App Service backend, but it will work with any Xamarin.Forms project looking to add Facebook login integration.

Setup

To start, you will need to create a Facebook app project and connect it to your Azure backend.  Azure has provided excellent instructions here on how to handle this, so I'll avoid copying everything in this post.

After following the Azure instructions, there are a few more steps you will need to take to prepare your project for Facebook SDK login.  Go to your project page on the Facebook developer site and select 'Facebook Login' from the menu on the left.  If you don't have 'Facebook Login' available, select 'Add Product' and choose 'Facebook Login'.   Now click 'Quickstart' and select 'Android' as a platform.  This will walk you through adding in the necessary settings for using the Facebook SDK with your Android app.  Most of the items you can skip through, but there are a few important ones to be sure to fill out:


  • Google Play Package Name - should be something like com.example.appname
  • Class Name - add .MainActivity to your Google Play Package Name
  • Key Hash - use the provided command to generate the development key hash, then copy and paste it into the given slot

PCL Project

The PCL Project will require relatively little work.  We will need to create a custom button, edit the App.cs file, and create a page to place the button on.

First, add the following line to your App class in App.cs:


public static Action<string> PostSuccessFacebookAction { get; set; }

This will allow us to send the token string from the Android project to the PCL project when we have authenticated the user.

Next, create a new button called FacebookLoginButton.  The class should look like this:

public class FacebookLoginButton : Button
{
}

This is actually all we will need to do with this class.  Since the Facebook SDK is platform specific, we will implement the functionality of this class in each platform project as a custom renderer.

Finally, create a Page to display the Facebook button and add the following code:

FacebookLoginButton facebookButton = new FacebookLoginButton();

App.PostSuccessFacebookAction = async token =>
    {
        //Here you have the Facebook token
        //do with it as you please!
        Debug.writeline("Token = " + token );
    };

The first line creates our Facebook login button; from there you can place it where ever you like in your layout.

The second portion is what handles receiving the login token from the Android project.  For now it just prints the token to the console.

That's it for the PCL project!

Android Project

The Android project requires a bit more work, but it's also not terribly complicated. 

Install Nuget Package

The first step is to install the Xamarin.Facebook.Android nuget package.  I installed version 4.11.0.1 because its dependencies matched the Android support libraries I was already using.

MainActivity

The next step is to get our MainActivity setup to run the Facebook SDK.
To start, add the following lines above your namespace declaration:

using Xamarin.Facebook;

[assembly: Permission(Name = Android.Manifest.Permission.Internet)]
[assembly: Permission(Name = Android.Manifest.Permission.WriteExternalStorage)]
[assembly: MetaData("com.facebook.sdk.ApplicationId", Value = "@string/app_id")]

[assembly: MetaData("com.facebook.sdk.ApplicationName", Value = "@string/app_name")]

These lines add in permissions required by the Facebook SDK and set the ApplicationId and ApplicationName variables.  We will add app_id and app_name to strings.xml shortly.

Next, we need to initialize the Facebook SDK.  To do so, add the following line just after "base.OnCreate(bundle);" in the OnCreate() method:


FacebookSdk.SdkInitialize(this);

Lastly, we need to set up the callback framework for the Facebook login manager.

Add this field to your MainActivity class:


public static ICallbackManager callbackManager;

Then add these lines after the "FacebookSdk.SdkInitialize(this);" line we added a little bit ago:

callbackManager = CallbackManagerFactory.Create();

Xamarin.Facebook.Login.LoginManager.Instance.RegisterCallback(callbackManager, new FacebookCallbackHandler());

And finally, add in this method to your MainActivity class:

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

}


FacebookCallbackHandler

You'll notice that at the end of the last section, we referenced the FacebookCallbackHandler.  Now it's time to implement this class.  The FacebookCallbackHandler will be responsible for handling our login callback.  It must implement 3 methods, OnError, OnCancel, and OnSuccess. This will be where we use PostSuccessFacebookAction to send the token back to the PCL project.

Here's the entire FacebookCallbackHandler class:
class FacebookCallbackHandler : Java.Lang.Object, IFacebookCallback, IDisposable
{
    public void OnCancel()
    {
    }

    public void OnError(FacebookException p0)
    {
    }

    public void OnSuccess(Java.Lang.Object p0)
    {
        LoginResult loginResult = (LoginResult)p0;
        App.PostSuccessFacebookAction(loginResult.AccessToken.Token);
    }
}

FacebookLoginButtonRenderer

The FacebookLoginButtonRenderer will do all of the heavy lifting for us.  Luckily, it's still a pretty simple class.  Pretty much all we do is extend the LoginButton renderer from the Facebook libraries, and then register our callback.

To begin, add in the following line above the namespace declaration so that the Xamarin system can recognize it as a custom renderer for the FacebookLoginButton class:
[assembly: ExportRenderer(typeof(FacebookLoginButton), typeof(FacebookLoginButtonRenderer))]

Next, add in the body of the class:
class FacebookLoginButtonRenderer : ViewRenderer<Xamarin.Forms.Button, LoginButton>
{
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
    {
        base.OnElementChanged(e);

        Activity _activity = this.Context as MainActivity;

        var loginButton = new LoginButton(this.Context);
        var facebookCallback = new FacebookCallbackHandler();

        loginButton.RegisterCallback(MainActivity.callbackManager, facebookCallback);
            
        base.SetNativeControl(loginButton);
    }
}

Properties/AndroidManifest.xml

The Facebook SDK requires you to register a FacebookActivity in your AndroidManifest.xml file.  This Activity is provided by the SDK already, so you just have to add the following lines in between the application tags:

<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" />

If the Facebook app isn't installed on the device, the Facebook SDK will open a web browser to complete login.  The following portion of code is optional; it allows the Facebook SDK to use the credentials of the user if they have logged onto Facebook via Chrome, rather than making the user retype their information.  It also goes between the application tags in the manifest file:

<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>

Resources/values/strings.xml

Go ahead and create this file if it doesn't exist already. It should look like this:

<?xml version="1.0" encoding="utf-8" ?> 
<resources>
  <string name="app_id">**Your App ID**</string>
  <string name="app_name">**Your App Name**</string>
  <string name="fb_login_protocol_scheme">fb1528045527236083</string>
</resources>


Conclusion

And there you have it! You should now have a Facebook login button that lets you authenticate via the Facebook app!


Saturday, September 20, 2014

Scaling Background Image with Unity 2D

Unity makes it easy to develop for multiple platforms at once, and the Unity 2D toolkit makes creating 2D games pretty straight forward.  But one piece that can often causes problems is ensuring that your game looks the same across platforms/devices.  There is a wide variety of aspect ratios and screen sizes among phones and tablets, and it can be difficult to properly scale your game to them.  This tutorial will walk you through creating a background image for your 2D game and ensuring it properly covers all screens.  It also assumes you have some basic knowledge of how to use and navigate Unity.

Our basic approach will be as follows:
1. Create an image of 800x600 to use for the background.  We will be creating it to fit some of the smallest screens, and then scaling up.
2. Import this into your Unity project.
3. Add in a scaling factor for the background sprite.
4. Adjust the orthographic size of the camera.

First, create a new 2D Unity project and a new scene.  Now create (or find) an 800x600 image to be used for the background.  I used paint.net to create my background.

Add the image to Unity as a sprite with a 'Pixels To Units' value of 100.  To do this, simply drag and drop it into the Assets folder, then click on it and adjust the values in the 'Inspector' view to match the following:

Now create a new sprite in your scene.  You can do this via the hierarchy or GameObject->create other->sprite.  Drag your image from the Asset view to the 'Sprite' field of the 'Sprite renderer' in the inspector of the new sprite you just created.  This is shown in the image below:

You now should see your background in the scene!! We are almost there, just 2 simple scripts left to go.  First, we will create the camera script.  In the hierarchy, select the 'Main Camera'.  Under the 'camera' section in the Inspector view, make sure your camera's 'Projection' field is set to 'Orthographic'.  Now click 'Add Component' and add a C# script named "MainCamera". We will use this script to set the orthographic size of the camera and to set the scaling factor for the background image.

Before the onStart() method, add in the following lines.  These will be the fields that we use to calculate the scaling factor and to inform other scripts of the scaling factor.

private static float background_width = 800.0f;
private static float background_height = 600.0f;
public static float pixelsToUnits = 100.0f;
public static Vector3 scalingFactor = new Vector3(
                                       Screen.width/background_width,                                             Screen.height/background_height,
                                       1.0f);

The first two fields are the width and height of our background image.  We created an 800x600 image, so we fill in those values here.  These must be 'static' because they are used to calculate the 'static' scalingFactor.  The next is the pixels to unit value.  This will be used to set the orthographic size of the camera later.  Finally, we calculate the scaling factor.  This will give us a factor to multiple our sprites by in order to make them properly fit on the device screen.  Note that as long as all of your sprites are created proportionally to the 800x600 background image, you can multiple your sprites by this same scaling factor and they will remain the same size relative to each other on any screen.

Now that we have set up the scaling factor, we must change the orthographic size of the camera.  The camera's viewing box is determined by a few factors.  The width varies with the aspect ratio, which is set automatically by taking the size of the screen you are currently using and dividing the width by the height.  The height of the viewing box is determined by the orthographic size.  The orthographic size is defined as half of the viewing box's height.  But this height is not measured in pixels.  It is instead measured in units.  If you have a screen of height 900 and a pixels per unit value of 100, you will want an orthographic size value of 4.5 ((900/100)/2) in order to see the whole image.

To do this, we will adjust the camera's orthographic size in the onStart() method using the formula:
(screen height) / (pixels per unit) / 2.

void Start() {
    camera.orthographicSize = (Screen.height / pixelsToUnits ) / 2;
}

Now the camera will adjust properly to the screen when the game starts.  The last piece is to ensure that the background image scales to the screen correctly.  To do this, select your background sprite in the hierarchy and create a new c# script component.

In the onStart() method, add the following bit of code:
void Start () {
    SpriteRenderer sr = GetComponent<SpriteRenderer>();
    transform.localScale = MainCamera.scalingFactor;

}

These few lines first get the SpriteRenderer associated with the background sprite, and then scales the sprite based on the scaling vector we created in the MainCamera script.

That's it! You now have a background image which will scale to any size device screen.