Updates to the Facebook SDK 3.0 (Beta) for Android

SDK Version: 

Facebook recently announced a major update to the Facebook SDK for Android that makes it much simpler to manage login, publish to Open Graph, and measure the traffic you're getting from Facebook. The new SDK is also backwards compatible, so you can easily take advantage of new features like mobile app install ads without having to update a lot of code.

This article will walk you through the most important changes to the SDK, including:

1. Sessions and session management
2. Login view and fragment classes
3. API calls to Facebook
4. New native views for choosing friends or places
5. Mobile app install ads

Sessions and session management

One of the most important differences between the new Facebook SDK 3.0 for Android and previous versions of the SDK is the increased modularity of the code. In earlier versions of the SDK, login, session state management, and API calls were all handled through a single base class, Facebook. You would instantiate a Facebook object using your App ID, then use it to call most Facebook-related methods. The SDK 3.0 for Android provides greater separation of concerns and new classes that let you handle these tasks more easily.

One of these new classes is the Session class. Session lets you authenticate a user and subsequently manage that user's connection with Facebook. Before, you would call facebook.authorize to log a user in, and facebook.isSessionValid() to check if the user had a valid session; you were also expected to monitor whether a user's access token required refreshing. All this is now managed through the Session object.

When you want to log a user in with Facebook, you'll need to instantiate a new Session object, like this:

  1. Session session = new Session(getApplicationContext());

Session objects have an associated private AccessToken object, which, as expected, handles the user's access token. When the Session is created, it attempts to initialize itself from a TokenCache, an object that is automatically created to store the user's most recent access token. If the cache exists, and contains a valid access token, the session will be created using that token. If none exists, or if the token has expired, the Session object will create a TokenCache with an empty AccessToken object that has no associated permissions. You do not need to do anything for this to happen.

Instances of Session have a state machine that controls their life cycle and can take the following states: CREATED, CREATED_TOKEN_LOADED, OPENING, OPENED, OPENED_TOKEN_UPDATED, CLOSED, and CLOSED_LOGIN_FAILED. They provide state change notification via a callback interface, StatusCallback. If your Activity extends FacebookActivity, you can also use the more general onSessionStateChange() method to observe changes in session state.

Once you have created a Session, it is either in the CREATED state (no valid access token at create time) or the CREATED_TOKEN_LOADED state (created from valid token TokenCache). To make any API call, your session must be taken from CREATED to OPEN by calling one of the Session.open() methods. Opening a session is the same as logging a user in to Facebook. This is where you specify the permissions you are asking for.

If your session is in the CREATED state, calling one of the open() functions will prompt your user to log in to Facebook; you will have to handle cases where login fails. If the session is in the CREATED_TOKEN_LOADED state, your user will not have to go through the login flow again.

Once you have logged a user in successfully and received an access token, Session automatically refreshes and extends the lifetime of this token if needed. If you need a new token-- say, for example, your user logged out of Facebook on their phone-- Session will automatically take your user through the authorization flow again. You no longer have to write code to extend the access token yourself.

NB: In the new SDK, we require that you ask only for read permissions when you first open a session. You should not prompt your user for publish permissions until the time at which they are actually publishing an action to Facebook. This increases user trust and the likelihood that your user will choose to publish stories from your app.

But what happened to your App ID? You're no longer using it to create the Facebook object, so you have to reference it somewhere else-- in the AndroidManifest.xml file. Add the following line to your manifest file to allow the SDK to identify your app on Facebook:

  1. <metadata android:name="com.facebook.sdk.ApplicationId" android:value= “@string/app_id"/>

Notice, too, that you'll have to add a string resource to your strings.xml file with your App ID.

  1. <string name="app_id">12345678910</string>

Login view and fragment classes

The pre-built LoginButton and LoginFragmentclasses in the SDK provide an additional layer of abstraction and handle the creation and update of the Session object for you.

The LoginButton is a view class that can easily be added to your app. Include it in your layout file like this:

  1. <com.facebook.LoginButton
  2.         android:id="@+id/authButton"
  3.         android:layout_width="wrap_content"
  4.         android:layout_height="wrap_content"
  5.         android:layout_gravity="center_horizontal"
  6.         android:layout_marginTop="30dp"
  7.         />

If you require only the basic permissions from your user, this is all the code you'll have to add before making API calls. If you want more permissions, declare a private LoginButton variable, and request permissions like this:

  1. LoginButton authButton = (LoginButton)view.findViewById(R.id.authButton);
  2. authButton.setReadPermissions(Arrays.asList("user_likes", "user_status"));

The button automatically manages the correct display text ("Login"/"Log out"), and creates the necessary Session.StatusCallback interfaces to notify you of changes to your user's login state.

If you don't want to use the pre-created LoginButton view, but still want the benefits of automatic Session and StatusCallback creation, you can use the LoginFragment class. It also provides the setReadPermissions(List permissions) and setPublishPermissions(List permissions) methods so you can specify what you're asking from your user.

In addition, you should add LoginActivity to your Android XML file to prevent window leaks during authorization. For example, this could happen if if the Activity containing the dialog is destroyed, for example if the user rotates the device.

API Calls to Facebook

The latest version of the SDK also makes it substantially easier to make asynchronous API calls and to batch requests for fewer calls to the service.

API calls are made through the new Request class. There are many ways to construct Request objects, depending on what you need them to do. Most Requests are instantiated using the current Session (to identify the user and the permissions they've granted your app) and the graph path at which data will be retrieved, created, or deleted (e.g. graph.facebook.com/me). You can also specify a Bundle of additional parameters to pass along with the Request. For example, if you are posting a checkin, the graph path should be "/me/checkins," and the Bundle of parameters should include the place ID and coordinates of the checkin. This is similar to how requests were sent in the old SDK.

You should define a Request.Callback to handle the response, like in the code snippet below:

  1. Bundle postParams = new Bundle();
  2.         postParams.putString("name", "Facebook SDK for Android");
  3.         postParams.putString("caption", "Build great social apps and get more installs.");
  4.         postParams.putString("description", "The Facebook SDK for Android makes it easier and faster to develop Facebook integrated Android apps.");
  5.         postParams.putString("link", "https://developers.facebook.com/android");
  6.         postParams.putString("picture", "https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png");
  8.         Request.Callback callback= new Request.Callback() {
  9.             public void onCompleted(Response response) {
  10.                 JSONObject graphResponse = response
  11.                                            .getGraphObject()
  12.                                            .getInnerJSONObject();
  13.                 String postId = null;
  14.                 try {
  15.                     postId = graphResponse.getString("id");
  16.                 } catch (JSONException e) {
  17.                     Log.i(TAG,
  18.                         "JSON error "+ e.getMessage());
  19.                 }
  20.                 FacebookException error = response.getError();
  21.                 if (error != null) {
  22.                     Toast.makeText(getActivity()
  23.                          .getApplicationContext(),
  24.                          error.getMessage(),
  25.                          Toast.LENGTH_SHORT).show();
  26.                     } else {
  27.                         Toast.makeText(getActivity()
  28.                              .getApplicationContext(),
  29.                              postId,
  30.                              Toast.LENGTH_LONG).show();
  31.                 }
  32.             }
  33.         };
  35.         Request request = new Request(session, "me/feed", postParams,  
  36.                               HttpMethod.POST, callback);

Once you've created your Request objects, you can execute them asynchronously using RequestAsyncTask:

  1. RequestAsyncTask task = new RequestAsyncTask(request);
  2.         task.execute();

If you have many API calls to make, you can batch up to 50 at once using RequestBatch. Create and execute a new RequestBatch like this:

  1. RequestBatch batch = new RequestBatch();
  3.         for ( Request request : myListOfRequests) {
  4.             batch.add(request);
  5.         }
  6.         batch.executeAsync();

We also provide Request methods for common tasks:

  • newMeRequest(Session session, Request.GraphUserCallback callback): creates a Request to retrieve the user's profile
  • • newMyFriendsRequest(Session session, Request.GraphUserListCallback callback): creates a Request to retrieve the user's friend list
  • • newUploadPhotoRequest(Session session, Bitmap image, Request.Callback callback): creates a new Request configured to upload a photo to the user's default photo album.
  • • newPlacesSearchRequest(Session session, Location location, int radiusInMeters, int resultsLimit, String searchText, Request.GraphPlaceListCallback callback): creates a new Request that is configured to perform a search for places near a specified location via the Graph API
  • • newStatusUpdateRequest(Session session, String message, Request.Callback callback): creates a Request to post a status to a user's news feed

Alongside the Request objects, the new SDK also includes a Graph Object interface that provides strongly-typed getters and setters for data fetched from the Graph API. For example, the GraphUser interface allows you to getBirthday(), and the GraphPlace interface contains the method getLocation().

New native views for choosing friends or places

We now also provide pre-built views for choosing friends or locations on Facebook within your app. The UI is exposed as a Fragment to allow it to be included in an Activity along with other Fragments if you wish. These PickerFragments support callbacks that will be called in the event of an error, when the underlying data has been changed, or when the set of selected graph objects changes.

There are detailed tutorials on how to implement the Friend Picker and the Place Picker available in the new Android Resource Center.

Mobile App Install Ads

You can now promote your mobile app directly in people's news feeds using Facebook's mobile app install ads. You can advertise this way regardless of whether your app uses Facebook. The SDK 3.0 features a method in the Settings class called publishInstallI(context, YOUR_APP_ID) that asynchronously pings an install event to Facebook when it's invoked. Include it in the onCreate() method of your app's launcher activity, like this:

  1. public void onCreate(Bundle savedInstanceState) {
  2.         super.onCreate(savedInstanceState);
  4.         Settings.publishInstall(getApplicationContext(), appId);
  5.                 ...
  6.    }

The Settings class internally handles tracking repeat calls to prevent multiple installs from the same device being published to the graph.

Once you have this line of code in your app, you can go to the App Dashboard to configure text and images for your ad, which will look something like this in a person's news feed:

A step-by-step walkthrough for setting up mobile app install ads is available here.

We hope you find the new methods and classes in the Facebook for Android SDK 3.0 useful and simple to implement. If you have feedback on how Facebook can make it better, please join the Facebook SDK 3.0 Beta Feedback group, and let us know!