Skip to content
peter edited this page Apr 27, 2014 · 1 revision

Welcome to the Drink2048 wiki Developers Apps Products Docs Tools Support

Log In Product Docs Login Overview iOS Android Web Windows Phone Permissions Access Tokens Testing Best Practices Advanced Sharing Games Payments Ads for Apps SDKs iOS Android JavaScript PHP Unity Third-Party APIs Graph API Ads API Facebook Login for Android

Facebook Login allows you to obtain a token to access Facebook's API on behalf of someone using your app. You can use this feature in place of building your own account system or to add Facebook services to your existing accounts.

The Facebook SDK for Android provides methods to implement Facebook Login for your app. The SDK provides Facebook Login support for the these common scenarios:

Your app uses only Facebook Login to authorize people using your app. Your app provides two login options: Facebook Login and your own login mechanism. Your app uses your own login initially and Facebook Login is an option to switch on certain social features. In cases (1) and (3), the Facebook SDK provides a UserSettingsFragment class that can be hosted by your login activity to display the Facebook login/logout button. In case (2), the Facebook SDK provides a LoginButton class that provides a button you can drop into your UI. The LoginButton class maintains the session state and is used to log people in and out.

In this document, we'll build on case (2) and show you how to implement Facebook Login with LoginButton. Many of the points also apply if you use the UserSettingsFragment class.

This document walks through the following topics:

Prerequisites App Dashboard configuration Sample overview Step 1: Implement the authentication flow Step 2: Set up authentication change triggers Step 3: Ask for additional permissions Troubleshooting Best practices Pro tip 1: Include Facebook Login when someone registers to use your app Pro tip 2: Request only the permissions you need Permissions Login dialogs Additional information Prerequisites

To use Facebook Login, you'll first need to add the Facebook SDK to your project. This section describes how to do that. If you already added the Facebook SDK to your project, skip to the next section.

See Getting Started with the Android SDK to complete the following tasks:

Install the Android development prerequisites

Install the Facebook SDK for Android and the Facebook APK

Import the SDK into your IDE (ex: Eclipse)

Create a Facebook app

Create a new Android project. Do not add the code related to a minimum viable project. Make sure you've set up a new Android app, linked your project to the Facebook SDK and configured the Android Manifest for your app ID and the LoginActivity.

During your project setup, use these values to follow along with the code samples in this doc:

Activity Name: MainActivity Layout Name: main Title: MainActivity Once you've gone through these steps, you can use methods in the SDK to implement Facebook Login in your app.

App Dashboard configuration

To properly handle Facebook Login using the Facebook for Android app, make the following changes in the App Dashboard:

Key Hash: Enter your app signature or key hash. If you don't have it yet, get your key hash.

Single Sign On: Enable this setting.

Sample overview

The completed sample allows people to log in with Facebook by tapping a button. After someone authenticates, they can tap the same button to log out. If the person already authenticated when the app launched, the app remembers the logged-in state and displays a logout button.

The Facebook SDK provides a LoginButton view that is a custom view implementation of a Button. You can use this button in your app to implement Facebook Login. The LoginButton class maintains the session state, which allows it to display the correct text in the button based on the authentication state. Adding LoginButton to your activity's layout is a quick way to implement Facebook Login.

Along with the login button, you may want to control other UI components based on whether the person is authenticated or not. The Facebook SDK includes two classes: UiLifecycleHelper and Session.StatusCallback, to handle much of the complexity around managing session state changes. The activity or fragment where you show authenticated functionality can create an instance of the UiLifecycleHelper class and pass in a Session.StatusCallback listener that is notified of any session state changes. Your activity or fragment must call UiLifecycleHelper public methods that mirror an activity's or fragment's lifecycle methods. These methods are used in creating, opening, saving, and restoring an active Facebook session. The Session.StatusCallback listener implementation can override the call() method to respond to session state changes and update the UI accordingly.

So LoginButton controls the login button functionality and you can add custom code triggered off the call() method to control other UI components.

1: Implement authentication

At the end of this step, someone using your app will be able to click a button to log in with Facebook.

First, you'll add a LoginButton button that the person can click to log in. You'll also set up a fragment to set up the UI.

Open up your main activity's layout XML file: res/layout/main.xml, and add the LoginButton button by specifying the full name of the class: com.facebook.widget.LoginButton. The result should look like this:

<com.facebook.widget.LoginButton
    android:id="@+id/authButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="30dp"
    />
Note: The BlankActivity template may create a default RelativeLayout root view. You'll use a LinearLayout root view instead.

Now that you have the UI defined, let's set up a fragment to display it. The fragment will be hosted by the main activity so you'll make some changes in the main activity class shortly to enable this.

Create a new class named MainFragment that's a subclass of the Fragment class.

Open up the class and override the onCreateView() method to set up the layout.

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.main, container, false);

return view;

} Note: If you get an error after this step or get one later about missing libraries, select Source->Organize Imports to include the required libraries if you're using Eclipse. Make sure to select android.support.v4.app.Fragment if given a choice of several imports.

You've set up your main fragment. Now, go back to your main activity and set it up to use your fragment.

First, make the activity subclass FragmentActivity instead of Activity:

public class MainActivity extends FragmentActivity { Next, define a private instance variable for your MainFragment class:

private MainFragment mainFragment; By default, the onCreate() method loads the layout in the main activity. Change this to add an instance of the MainFragment class to the activity during the initial setup or to set the instance after the saved state is restored:

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

if (savedInstanceState == null) {
    // Add the fragment on initial activity setup
    mainFragment = new MainFragment();
    getSupportFragmentManager()
    .beginTransaction()
    .add(android.R.id.content, mainFragment)
    .commit();
} else {
    // Or set the fragment from restored state info
    mainFragment = (MainFragment) getSupportFragmentManager()
    .findFragmentById(android.R.id.content);
}

} The authentication flow initializes the Facebook SDK, opens the session and requests basic permissions.

2: Authentication change triggers

In this step, you'll add code to control any additional UI based on the authentication state. For example, after someone authenticates, you may want your app to show a new button alongside the logout button. This new button may perform some functionality that requires the person have a valid Facebook session, and therefore you may want to make it hidden until the authentication is complete. You won't add any UI components in this step, but you'll see how you can set them up.

The UiLifecycleHelper class constructor takes in a Session.StatusCallback listener implementation that you can use to respond to session state changes by overriding the listener's call() method. You'll define a private method in your main fragment class called onSessionStateChange() that is invoked from the call() method. You'll primarily be interested in session state changes that transition to opened or closed.

First, create a string constant that you'll use for debug logging purposes:

private static final String TAG = "MainFragment"; Next, open up the MainFragment class and define a private method that can control the UI:

private void onSessionStateChange(Session session, SessionState state, Exception exception) { if (state.isOpened()) { Log.i(TAG, "Logged in..."); } else if (state.isClosed()) { Log.i(TAG, "Logged out..."); } } When the session state is open, you can display your authenticated UI, such as making a new button visible. When the state is closed, you can display the non-authenticated UI, such as hiding the new button.

Now that you've added logic to respond to session state changes, you'll add logic to listen for the changes. Define a private variable that contains the implementation of the Session.StatusCallback listener:

... private static final String TAG = "MainFragment";

private Session.StatusCallback callback = new Session.StatusCallback() { @Override public void call(Session session, SessionState state, Exception exception) { onSessionStateChange(session, state, exception); } }; You'll pass this listener as a parameter to the UiLifecycleHelper constructor. Define a private variable for the UiLifecycleHelper instance:

private UiLifecycleHelper uiHelper; Next, override the onCreate() method to create a new UiLifecycleHelper object, passing in the callback variable you defined earlier:

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); uiHelper = new UiLifecycleHelper(getActivity(), callback); uiHelper.onCreate(savedInstanceState); } To ensure that the sessions are set up correctly, your fragment must override the fragment lifecycle methods: onCreate(), onResume(), onPause(), onDestroy(), onActivityResult() and onSaveInstanceState() and call the corresponding UiLifecycleHelper methods. For example, calling the onCreate() method in the UiLifecycleHelper object creates the Facebook session and opens it automatically if a cached token is available.

Add the following code to make those changes:

@Override public void onResume() { super.onResume(); uiHelper.onResume(); }

@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); uiHelper.onActivityResult(requestCode, resultCode, data); }

@Override public void onPause() { super.onPause(); uiHelper.onPause(); }

@Override public void onDestroy() { super.onDestroy(); uiHelper.onDestroy(); }

@Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); uiHelper.onSaveInstanceState(outState); } During the authentication flow, the results are returned back to the main activity by default. Your activity would need to handle the results by overriding the onActivityResult() method. To allow the fragment to receive the onActivityResult() call rather than the activity, you can call the setFragment() method on the LoginButton instance. To set this up, add the following code to the onCreateView() method before you return a view:

... LoginButton authButton = (LoginButton) view.findViewById(R.id.authButton); authButton.setFragment(this);

return view; ... There are scenarios where the onSessionStateChange() notification may not be triggered when the main activity is launched. This may happen when your app is launched from the Facebook for Android app through a bookmark link as an example. For these type of scenarios, trigger the onSessionStateChange() method whenever fragment is resumed. This will in turn properly set the authenticated or non-authenticated UI. To do this modify the onResume() method to add the following code:

....
// For scenarios where the main activity is launched and user
// session is not null, the session state change notification
// may not be triggered. Trigger it if it's open/closed.
Session session = Session.getActiveSession();
if (session != null &&
       (session.isOpened() || session.isClosed()) ) {
    onSessionStateChange(session, session.getState(), null);
}

uiHelper.onResume();

} Build and run your project. Log in with Facebook. You should be taken through the permissions screen. After accepting the permissions, you should be brought back to the login screen and the button should have log out text. If you don't have the Facebook for Android app installed, you'll be asked to log in within a browser during the authentication step. You can tap the logout button to close the session. The button should now have log in text. You should also see a console message from when someone logged in logged out.

Note: You can add the UiLifecycleHelper and set up a corresponding Session.StatusCallback listener in any activity or fragment where you wish to track and respond to session state changes.

3: Ask for additional permissions

A real world app usually asks for permissions other than the basic permissions that are granted by default. A full list of permissions is available in our permissions reference. You can pass in the permissions your app needs when you open a Facebook session.

To do this, you'll ask for these additional permissions: user_likes and user_status. You can pass in these permissions to the LoginButton button when you create the view.

Open up the MainFragment class and modify the code in the onCreateView() method:

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

return view; ... Build and run your project. During the authentication flow, you should see a prompt for additional permissions:

If you're using this project for the tutorial that builds on this doc, delete or comment out the line that sets the permissions:

... //authButton.setReadPermissions(Arrays.asList("user_likes", "user_status"));

return view; ... Troubleshooting

If you're testing Facebook Login with the Facebook for Android app, and any of the following happens, you may have a problem with the key hash you provided to the App Dashboard:

You get the native Login Dialog permissions, and after that the person is not authenticated. The logcat also contains this exception:

12-20 10:23:24.507: W/fb4a:fb:OrcaServiceQueue(504): com.facebook.orca.protocol.base.ApiException: remote_app_id does not match stored id You are shown a non-native Login Dialog that includes an error message at the top: ''..App is Misconfigured for facebook login...''.

Here are some resources to troubleshoot this:

Key Hash Reference Doc: Signing Your Applications.

Keytool command not found error: Keytool is provided by the standard Java JDK. If you get ''Command not found'' error, you need to add the path to your global ''PATH'' or go to the folder to run this command. Windows: C:\Program Files (x86)\Java\jdk1.6.0\bin, MAC: /usr/bin.

Openssl: If you don't have openssl, install it from here: Windows, MAC.

Invalid Key Hash: The keytool silently generates a key hash regardless of unknown debug.keystore location or wrong password. If you get exceptions or visual cues related to an invalid key hash there are few possibilities:

keytool couldn't find your debug.keystore location. Make sure you provide the correct path. One way to know is keytool should always ask for a password when it has the correct location.

The password you entered is incorrect. The default Keystore password: "android".

You need to click 'Save Changes' when adding a key hash to the App Dashboard on Facebook.

If this fails, try using cygwin or linux box to generate keyhash.

Another option is to print out the key hash sent to Facebook and use that value. Make the following changes to the onCreate() method in your main activity:

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

try {
    PackageInfo info = getPackageManager().getPackageInfo(
            "com.facebook.samples.loginhowto", 
            PackageManager.GET_SIGNATURES);
    for (Signature signature : info.signatures) {
        MessageDigest md = MessageDigest.getInstance("SHA");
        md.update(signature.toByteArray());
        Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
        }
} catch (NameNotFoundException e) {

} catch (NoSuchAlgorithmException e) {

}
...

Replace com.facebook.samples.loginhowto with your own package name.

Permissions

Request basic permissions

When the user logs in, apps must request the basic_info permissions.

Here's an example using the LoginButton class in the Facebook SDK for Android:

... LoginButton authButton = (LoginButton) view.findViewById(R.id.authButton); authButton.setReadPermissions(Arrays.asList("basic_info")); ... Here's an example using Session methods to initiate the login flow:

private Session.StatusCallback statusCallback = new SessionStatusCallback(); ... private void onClickLogin() { Session session = Session.getActiveSession(); if (!session.isOpened() && !session.isClosed()) { session.openForRead(new Session.OpenRequest(this) .setPermissions(Arrays.asList("basic_info")) .setCallback(statusCallback)); } else { Session.openActiveSession(getActivity(), this, true, statusCallback); } } ... private class SessionStatusCallback implements Session.StatusCallback { @Override public void call(Session session, SessionState state, Exception exception) { // Respond to session state changes, ex: updating the view } } When a user clicks “OK”, the app is granted access to the user's basic profile info.

Request read permissions

Apps can also choose to request additional read permissions beyond the basic profile permissions. For example, they may use them to show a list of photos by a user and their friends, or to display the recent checkins of a user, etc. To allow the user to grant these permissions, make this request with the Facebook SDK for Android using:

... Session.NewPermissionsRequest newPermissionsRequest = new Session .NewPermissionsRequest(this, Arrays.asList("user_checkins")); session.requestNewReadPermissions(newPermissionsRequest); ... This method is used to request permissions in addition to what the app has already been granted. This happens after an initial connection has been made to Facebook as described in Step 1.

You can request many of the read permissions listed in our permissions reference.

Request publish permissions

A feature of the sample Scrumptious app is the ability to announce that you are eating at a particular place. To add this to their timeline, the user must grant the app a publish permission that lets the app publish content on their behalf. The first time the user taps on the 'announce' button, the app will request publish_actions permission. To make this request with the Facebook SDK, use:

... Session.NewPermissionsRequest newPermissionsRequest = new Session .NewPermissionsRequest(this, Arrays.asList("publish_actions")); session.requestNewPublishPermissions(newPermissionsRequest); ... This method is used to request permissions in addition to what the app has already been granted. This happens after an initial connection has been made to Facebook as described in Step 1.

Publish permissions include:

Permissions publish_actions ads_management create_event rsvp_event manage_friendlists manage_notifications manage_pages Login dialogs

When people using your app initiate authentication using their Facebook credentials for the first time, they will be shown a dialog prompting them to accept the permissions you're requesting on login. The same will happen when you request additional permissions later on.

The SDK has three different kinds of login dialogs that it can show the user. The type of dialog that will appear depends on the Facebook for Android application that the user has installed on their device, and is automatically determined by the SDK. These are the three options:

If the user doesn't have the Facebook for Android app installed on their device, they will be shown a web login dialog inside a WebView.

If the user has Facebook for Android 1.9.X or older, login and permission requests will be made by doing a fast-app-switch to Facebook for Android and showing a native login dialog inside the Facebook for Android app.

The login Dialog built into Facebook for Android 2.0+ gives developers a native way to use Facebook Login in their apps without having to make a fast-app-switch to Facebook for Android. If the user has a version of Facebook for Android 2.0 or newer, they will see the following:

Additional information

Session: reference for the session class UiLifecycleHelper: reference for the UiLifecycleHelper class Session.StatusCallback: reference for the Session.StatusCallback class SessionLoginSample: sample included in the SDK that shows how to use Facebook Login Was this document helpful?YesNo

Clone this wiki locally