Monday, June 6, 2011

Facebook Integration in your Android Application

Introduction

The goal of this article is to get Facebook integration up & running from your Android app in 30 minutes. The guide will show you how to
setup a Faceook test account
register a Facebook application
authenticate the user in your Android application.
have the user update his Facebook wall from your Android application.
This guide is accompanied  by a sample application that’s available in Github in the AndroidFacebookSample repository. To import this project in Eclipse, I suggest using the EGit plugin that can be installed via the Main P2 Repository located at http://download.eclipse.org/egit/updates.
Before running this project, make sure you change the com.ecs.android.facebook.Sample.AndroidFacebookSample file to include your Facebook API key (see subsequent section).
Once you have sample application up & running, you can copy the relevant classes into your projects to have Facebook up & running from your Android application.
First things first … In order to integrate with Facebook, you need 2 things:
A Facebook test account, used in our Android application to login to Facebook and make status updates.
A Facebook application, used to inform the user in your Android application that this application is requesting you to login to Facebook.
The goal of this article is to get Facebook integration up & running from your Android app in 30 minutes. The guide will show you how to
  • setup a Faceook test account.
  • register a Facebook application.
  • authenticate the user in your Android application.
  • have the user update his Facebook wall from your Android application.
integrate_facebook_android_app_01

This guide is accompanied  by a sample application that’s available in Github in the AndroidFacebookSample repository. To import this project in Eclipse, I suggest using the EGit plugin that can be installed via the Main P2 Repository located at http://download.eclipse.org/egit/updates.

Before running this project, make sure you change the com.ecs.android.facebook.Sample.AndroidFacebookSample file to include your Facebook API key (see subsequent section). Once you have sample application up & running, you can copy the relevant classes into your projects to have Facebook up & running from your Android application.

First things first … In order to integrate with Facebook, you need 2 things:
  • A Facebook test account, used in our Android application to login to Facebook and make status updates.
  • A Facebook application, used to inform the user in your Android application that this application is requesting you to login to Facebook.


Facebook Test Account

We’ll start by creating a test account that we’ll use in our Android application. Signup for a new user account at Facebook. If you already have an account, sign up for a new account using your existing name but specify a different email address. Once the account has been created, we’ll convert it into a Facebook test account.

Note: The following step should not be done on your real facebook account. Converting an existing Facebook account into a test account is irreversible, so please ensure that you do the following step with your newly created “dummy” account.

When logged into Facebook, goto the Facebook Become Test Account page  to convert your newly created account into a Facebook test account. Again, do not execute these steps on your “real” user account.

integrate_facebook_android_app_02

After confirming that you want to convert your account into a test account, you should see the following message:

integrate_facebook_android_app_03



Facebook Application

Next step is to create a Facebook application. Integration with facebook is based on OAuth 2.0 and requires your to register a Facebook application. Visit the Facebook Developers Authentication page for more information on its OAuth 2.0 implementation.

The Facebook application that we’ll create will have it’s own Application ID that we’ll use in our Android application.

Creating an application cannot be done on the Facebook test account, so you’ll need to have a proper Facebook account in order to create the application. Using your “real” Facebook account, goto the Facebook Create Application page  and create your application.

integrate_facebook_android_app_04

Give it a name, and complete the registration. You should land on a page like this:

integrate_facebook_android_app_05

So far so good, everything is setup on the Facebook front, now it’s time to start coding our Android application.

On the Android front, we’ll use the Facebook Android SDK located at Github: https://github.com/facebook/facebook-android-sdk.

The Facebook Android SDK is licensed under the Apache License and is completely open source.

integrate_facebook_android_app_06

The project contains several samples in the examples folder, but the core SDK is located in the facebook folder. The sample application included in the facebook sdk repository provides the user the ability to post a message on the wall using a custom dialog, allowing the user to enter some text. The goal of the sample application that we’ll be creating here is to send an automated message to the wall, without any human interaction. Our application will generate a piece of text and post it on the wall without showing a dialog to the user. The user simply presses a button, and the generated message will appear on his/her wall.

But to get started, we’ll begin by importing the facebook project (containing the actual facebook sdk) into Eclipse. Once this is done, you should have the following Eclipse Project in your workspace:

integrate_facebook_android_app_07

As this is the library project that our sample application will use to do the actual  Facebook integration, we’ll  need to create a reference in our own project to this Facebook Android SDK project. This is done by going to our project properties, select Android on the left, go to the library section and click Add.

integrate_facebook_android_app_08

On the following screen, you can select the Facebook Android SDK library project

integrate_facebook_android_app_09

When selected, it will be made available to your own project.

integrate_facebook_android_app_10

As you can see in the Eclipse Package explorer, our sample project now also contains a reference to the Facebook Android SDK project

integrate_facebook_android_app_11

The Facebook SDK project revolves around a central com.facebook.android.Facebook.Facebook class, allowing you to perform various calls to Facebook.  It provides basic login/logoff functionality (by leveraging single sign on capabilities if you have the official facebook app installed), handles the OAuth integration, and provides you with a generic API to perform requests to the various Facebook APIs.

In our own sample application
, we’ll encapsulate all the Facebook interactions in a FacebookConnector object. The object is constructed like this:

1
2
3
4
5
6
7
8
9
10
11
12
public FacebookConnector(String appId,Activity activity,Context context,String[] permissions) {
 this.facebook = new Facebook(appId);
 
 SessionStore.restore(facebook, context);
       SessionEvents.addAuthListener(mSessionListener);
       SessionEvents.addLogoutListener(mSessionListener);
 
 this.context=context;
 this.permissions=permissions;
 this.mHandler = new Handler();
 this.activity=activity;
}

As you can, under the hook, our FacebookConnector class uses the Facebook class provided by the Facebook SDK project.

Our FacebookConnector will provide a more coarse-grained API than the Facebook class. The Facebook class is designed in a very generic way, allowing you to do a lot of different calls to Facebook. This design results in a fairly fine-grained API, where some knowledge is expected from the application using this API. For example, you’ll need to know the specific endpoints for post a message on a wall, or to retrieve a user profile. In addition to that, you’ll also need to know what parameters you need to send for each request.

Our FacebookConnector exposes a coarse-grained method called postMessageOnWall that’s the main logic behind our Post button. The only thing we need to provide is the actual message we want to post. The FacebookConnector will do the necessary plumbing towards the more generic Facebook class.

The postMessageOnWall method checks if we have a valid Facebook session (meaning we have authenticated properly against Facebook). If this is the case, it setups up the necessary parameters, and does a call through the Facebook class to post a message on the wall. (using the me/feed endpoint)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void postMessageOnWall(String msg) {
 if (facebook.isSessionValid()) {
     Bundle parameters = new Bundle();
     parameters.putString("message", msg);
     try {
   String response = facebook.request("me/feed", parameters,"POST");
   System.out.println(response);
  } catch (IOException e) {
   e.printStackTrace();
  }
 } else {
  login();
 }
}

But we’ll start by explaining what happens if the user doesn’t have a valid Facebook session.

If the user hasn’t authenticated to Facebook yet we need to perform a login. The login() is defined like this:

1
2
3
4
5
public void login() {
       if (!facebook.isSessionValid()) {
           facebook.authorize(this.activity, this.permissions,Facebook.FORCE_DIALOG_AUTH,new LoginDialogListener());
       }
   }

The login method is implemented in such a way that when we don’t have a logged in user, we call the facebook.authorize to start the Facebook OAuth flow. Although the Facebook SDK has a single-sign-on option, allowing you to leverage your existing facebook session you may have with the official Facebook Android application, we’ll add the Facebook.FORCE_DIALOG_AUTH parameter to have the Facebook SDK pop the login dialog.

The first thing that will happen when executing this method, is that the Facebook login dialog will be shown. Notice how the login dialog mentions the Facebook app we created earlier. By passing on our Application ID to the Facebook object, the user is now informed that the TestAndroidIntegration application is initiating the Facebook login. The user can decide at this point if he wants to login to his Facebook account.

integrate_facebook_android_app_12

When the user does a login, he’ll be presented with yet another dialog. Keep in mind that at this point, although the user is logged in, he didn’t give any permissions yet for this application to post messages on his wall. This particular dialog will now request the user for certain permission.

It basically allows the user to authorize the TestAndroidIntegration application to access basic information and Post to my Wall.  Accessing basic information is the default permission that is given when a user logs in this way. Here, an additional permission is requested (Post to my Wall).

In order to post something on the wall, the publish_stream permission is required, hence we pass this on to our FacebookConnector:

1
2
3
4
private static final String FACEBOOK_APPID = "PUT YOUR FACEBOOK APPID HERE";
private static final String FACEBOOK_PERMISSION = "publish_stream";
 
facebookConnector = new FacebookConnector(FACEBOOK_APPID, this, getApplicationContext(), new String[] {FACEBOOK_PERMISSION});

Note: ensure that you provide a proper Facebook APPID here.

integrate_facebook_android_app_13

When the user allows this request for permission (authorization), the Facebook API can begin executing requests on behalf of the user (like posting something on his wall).



Posting a message on the Facebook wall

In order to post a message on the wall, we basically construct a message (Bundle) that we pass on to the facebook request method. We use the “me/feed” ID on the Facebook Graph API to indicate that we’ll be posting something to the Profile feed (Wall in Facebook terminlogy).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private FacebookConnector facebookConnector;
 
private void postMessageInThread() {
 Thread t = new Thread() {
  public void run() {
 
      try {
       facebookConnector.postMessageOnWall(getFacebookMsg());
    mFacebookHandler.post(mUpdateFacebookNotification);
   } catch (Exception ex) {
    Log.e(TAG, "Error sending msg",ex);
   }
     }
 };
 t.start();
}

The postMethodOnWall() method is called from our main Activity in a background thread. Although we don’t want to interrupt the main UI thread while posting the message (hence the background thread), we do want to send a notification to the user that his message was posted. We use a handler for this in order to show a Toast message on the main UI thread once the background processing has been done.

1
2
3
4
5
6
7
private FacebookConnector facebookConnector;
 
   final Runnable mUpdateFacebookNotification = new Runnable() {
       public void run() {
        Toast.makeText(getBaseContext(), "Facebook updated !", Toast.LENGTH_LONG).show();
       }
   };

An importing thing to note is that when the user clicks the Post Message button, besides logging just logging in, we also want to send the message to the Facebook wall. Performing the login, immediately followed by an action (in this case sending a message) can be done by adding a AuthenticationListener (SessionEvents.AuthListener) to the SessionEvents.

The following code (wrapper method) illustrates this :
  • in case of logged in user simply post the message in the background thread.
  • in case of an anonymous user, we wait for the authentication to succeed, and then continue on to posting the message in the background thread.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void postMessage() {
 if (facebookConnector.getFacebook().isSessionValid()) {
  postMessageInThread();
 } else {
  SessionEvents.AuthListener listener = new SessionEvents.AuthListener() {
 
   @Override
   public void onAuthSucceed() {
    postMessageInThread();
   }
 
   @Override
   public void onAuthFail(String error) {
 
   }
  };
  SessionEvents.addAuthListener(listener);
  facebookConnector.login();
 }
}

The clearCredentials() method is responsible for logoff functionality. All credentials are cleared from the system, and each interaction with Facebook will again trigger a login().

1
2
3
4
5
6
7
8
9
private void clearCredentials() {
 try {
  facebookConnector.getFacebook().logout(getApplicationContext());
 } catch (MalformedURLException e) {
  e.printStackTrace();
 } catch (IOException e) {
  e.printStackTrace();
 }
}

1 comment: