농부와 컴퓨터/FACEBOOK

Facebook Android Tutorial...

금오귤림원 2011. 12. 20. 22:40

Android Tutorial

This document will guide you through Facebook Platform integration for Android. We will walk you through a tutorial to show the key steps to building a social Android app. This will include showing you how to enable Single Sign-On. We will also cover additional topics around integrating with Facebook Platform.

Getting started

  1. Register your Android App with Facebook
  2. Download and install the Android SDK

Prepare your project

  3. Create New Facebook SDK Project
  4. Add reference to the Facebook SDK
  5. Add your app's signature to the Facebook App Settings

Single Sign On

  6. Enable Single Sign-On for your App

    6.1. Modify AndroidManifest.xml for the Network calls
    6.2. Single-Sign-On (SSO)
    6.3. Install the Facebook Android App
    6.4. Build and run the project
    6.5. More permissions
    6.6. Save your access token

  7. Enable user to Log Out of your App

Adding social context

  8. Use the Graph API
  9. Social Channels
  10. Timeline and Open Graph

Error Handling

Handle Errors
Tips
Troubleshoot

Samples

Hackbook for Android
Open Graph Wishlist


Step 1: Register your Android app with Facebook

To begin integrating with the Facebook Platform, create a new app on Facebook and enter your app's basic information.


Note your App ID. You are going to need it when integrating Facebook Android SDK into your code. 
You application is now set up and you’re ready to begin integrating with Facebook!


Step 2: Download and install the Android SDK


Step 3: Create New Facebook SDK Project

For the first time, you will need to create a new Android project for the Facebook SDK source which can be reference from your app. This is only required once. Open Eclipse and create a new Android Project (File | New | Project | Android Project) for the Facebook Android SDK source and later reference it from your app. Get the content by selecting Create project from existing source and specifying the facebook directory from your git repository (~/facebook-android-sdk/facebook).


Step 4: Add reference to the Facebook SDK

Create a new Android project for your app or use your existing project and add a reference to the Facebook SDK project. You do this by opening the properties window for your app (File | Properties | Android), pressing the Add... button in the Library area and selecting the Facebook SDK project created above.


Step 5: Add your app's signature to the Facebook App Settings

Facebook requires an additional layer of security for mobile apps in the form of an application signature. You need to put your Android application signature into your Facebook application settings. You can generate a signature by running the keytool that comes with the Android SDK. The following shows how to export the key for your app using the debug defaults specified by the Android SDK and Eclipse.

PLEASE READ - the keytool.exe silently generates a keyhash even if it can't find the debug.keystore or if the password is incorrect. Make sure that you have provided the correct path to the debug.keystore. For Windows, it is generally at C:\Users\<user>\.android\ and for Mac at /Users/<user>/.android/Also make sure you are using the correct password - for the debug keystore, use 'android' to generate the keyhash. General Rule: If the tool does not ask for password, your keystore path is incorrect. More info under 'Signing in Debug Mode' on the Signing Your Applications. Refer to Troubleshoot section below for more tips on keyhash.

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

This tool generates a string that must be registered in the Mobile section of the Developer App for your app. Remember to click 'Save Changes' to save the keyhash.


Step 6: Enable Single Sign-On for your App

Single Sign-On allows user to authorize your app without typing their facebook username and password. This is accomplished by sharing intent with the Facebook app. If the user has already installed and authorized the facebook app, your app can leverage the Facebook app authentication via Single Sign On. It is highly recommended that you implement SSO for your app to enable frictionless authorization.Note that the SSO will fall back to webview based oauth dialg if the Facebook app is not installed on the handset.

Step 6.1: Modify the AndroidManifest.xml for the Network calls


Once the Facebook SDK is referenced, the app manifest needs to be modified to allow the app to make network calls to Facebook. This is accomplished by adding the following to the AndroidManifest.xml file in the app project (Note that by default the Eclipse may open the Manifest tab. Click on the AndroidManifest.xml tab in the editor's bottom bar to open the editor view):

<uses-permission android:name="android.permission.INTERNET"/>

Step 6.2: Single-Sign-On (SSO)


As with the iOS SDK, one of the most compelling features of the Android SDK is Single-Sign-On (SSO). SSO lets users sign into your app using their Facebook identity. If they are already signed into the Facebook Android app on their device they do not have to even type a username and password. Further, because they are signing to your app with their Facebook identity, you will have access to their profile information and social graph.

Adding SSO to your app is very simple with the Facebook SDK. The below example outlines what code must be written to enable this feature. For the sake of simplicity, SSO functionality will be added to the Activity that was created by Eclipse when the app project was created. Open the MyGreatApp project -> src -> com.greatapp -> MyGreatActivity.java. Replace the existing code by Copy-paste the code below while replacing the "YOUR_APP_ID" with the "APP_ID" of your app and save the file:

package com.greatapp;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.android.*;
import com.facebook.android.Facebook.*;

public class MyGreatActivity extends Activity {

    Facebook facebook = new Facebook("YOUR_APP_ID");

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        facebook.authorize(this, new DialogListener() {
            @Override
            public void onComplete(Bundle values) {}

            @Override
            public void onFacebookError(FacebookError error) {}

            @Override
            public void onError(DialogError e) {}

            @Override
            public void onCancel() {}
        });
    }

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

        facebook.authorizeCallback(requestCode, resultCode, data);
    }
}

Step 6.3: Install the Facebook Android App


To help with debugging your app in the Android emulator, we provide a binary image of the Facebook Android that you can install with the adb tool in the Android SDK. Launch the emulator for the Android 2.2 (the target selected when creating the project) by going to Window -> Android SDK and AVD Manager):

Run the following command. The adb tool is part of the standard android SDK and located in the android_sdk/platform-tools/ folder.

adb install ~/facebook-android-sdk/Facebook.apk

Your app will still work without installing this image, but we will default to using Platform Dialogs for sign-in rather than using the Facebook App requiring user to sign-in every time you run your app in the emulator.

Step 6.4: Build and run the project


Build and run the 'MyGreatApp' project. This should launch in the same emulator where you install the Facebook.apk. You will be prompted with the user authorization dialog (You may have to login to the Facebook app if not already done so):

This dialog allows the user to grant your app permission to access their information. If the user presses Allow, your app is authorized and you will have access to the user's profile and social graph through the facebook instance. If the user presses Don't Allow, your app is not authorized and you will not have access to the user's data.

Step 6.5: More permissions


By default, the user is asked to authorize the app to access basic information that is available publicly or by default on Facebook. If your app needs more than this basic information to function, you must request specific permissions from the user. This is accomplished by passing String[] of permissions to the authorize method. The following example shows how to ask for access to user's email address, get extended access token and check-in user at a place:

facebook.authorize(this, new String[] { "email", "offline_access", "publish_checkins" },

      new DialogListener() {
           @Override
           public void onComplete(Bundle values) {}

           @Override
           public void onFacebookError(FacebookError error) {}

           @Override
           public void onError(DialogError e) {}

           @Override
           public void onCancel() {}
      }
);

This shows an additional permissions screen where user can allow access to all, some or none permissions:

A full list of permissions is available in our permissions reference. There is a strong inverse correlation between the number of permissions your app requests and the number of users that will allow those permissions. The greater the number of permissions you ask for, the lower the number of users that will grant them; so we recommend that you only request the permissions you absolutely need for your app.

Step 6.6: Save your access token


If you run the project again (after user has initially authorized your app), you will notice that user is presented with the following dialog:

This dialog is displayed to mask the abrupt app-switching between your app and the Facebook app while Facebook SDK gets the access token for your app. To get rid of this dialog, let's rework on the previous code by using the Shared Preferences.

package com.greatapp;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.facebook.android.*;
import com.facebook.android.Facebook.*;

public class MyGreatActivity extends Activity {

    Facebook facebook = new Facebook("YOUR_APP_ID");
    String FILENAME = "AndroidSSO_data";
    private SharedPreferences mPrefs;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        /*
         * Get existing access_token if any
         */
        mPrefs = getPreferences(MODE_PRIVATE);
        String access_token = mPrefs.getString("access_token", null);
        long expires = mPrefs.getLong("access_expires", 0);
        if(access_token != null) {
            facebook.setAccessToken(access_token);
        }
        if(expires != 0) {
            facebook.setAccessExpires(expires);
        }
        
        /*
         * Only call authorize if the access_token has expired.
         */
        if(!facebook.isSessionValid()) {

            facebook.authorize(this, new String[] {}, new DialogListener() {
                @Override
                public void onComplete(Bundle values) {
                    SharedPreferences.Editor editor = mPrefs.edit();
                    editor.putString("access_token", facebook.getAccessToken());
                    editor.putLong("access_expires", facebook.getAccessExpires());
                    editor.commit();
                }
    
                @Override
                public void onFacebookError(FacebookError error) {}
    
                @Override
                public void onError(DialogError e) {}
    
                @Override
                public void onCancel() {}
            });
        }
    }

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

        facebook.authorizeCallback(requestCode, resultCode, data);
    }
}

If you save and run this (remember to replace "YOUR_APP_ID" with your app_id, you will notice that no authorization or confirmation dialog is displayed and user stays within your app. So, what's changed:

  • The access token is saved using SharedPreferences in the onComplete() method
  • The saved access token is fetched from persistent storage and set as the facebook object's access token viafacebook.setAccessToken()
  • facebook.authorize() is called only if the session is invalid. (checked by calling the facebook.isSessionValid()).

However, note that this doesn't account for the situation where user may have revoked access to your app or if user has changed his password. You will need to always look out for the invalid access_token and redirect user to re-authorize your app. For invalid access token, following error is returned in the 'response' parameter of the onComplete() method:

User revoked access to your app:
{"error":{"type":"OAuthException","message":"Error validating access token: User 1053947411 has not authorized application 157111564357680."}}

OR when password changed:
{"error":{"type":"OAuthException","message":"Error validating access token: The session is invalid because the user logged out."}}

Step 7: Enable user to Log Out of your App

When the user wants to stop using Facebook integration with your app, you can call the logout method to clear the app state and make a server request to invalidate the current access_token.

     mAsyncRunner.logout(getContext(), new LogoutRequestListener());

Note that logging out will not revoke your application's permissions, but will simply clear your application's access_token. If a user that has previously logged out of your app returns, they will simply see a notification that they are logging into your app, not a notification to grant permissions. You can revoke application's permissions by issuing the following api call:

     String method = "DELETE";
     Bundle params = new Bundle();
     /*
      * this will revoke 'publish_stream' permission
      * Note: If you don't specify a permission then this will de-authorize the application completely.
      */
     params.putString("permission", "publish_stream");
     mAsyncRunner.request("/me/permissions", params, method, new RevokePermissionListener(), null);

Also, the user can visit the "Applications, Games, and Websites" tab of their Facebook privacy settings dashboard.


Step 8: Use the Graph API

The Facebook Graph API presents a simple, consistent view of the Facebook social graph, uniformly representing objects in the graph (e.g., people, photos, events, and fan pages) and the connections between them (e.g., friend relationships, shared content, and photo tags).

You can access the Graph API by passing the Graph Path to the request method. For example, to access information about the logged in user, call:

    // get information about the currently logged in user
    mAsyncRunner.request("me", new meRequestListener());

    // get the posts made by the "platform" page
    mAsyncRunner.request("platform/posts", new pageRequestListener());

    // get the logged-in user's friends
    mAsyncRunner.request("me/friends", new friendsRequestListener());

The second paramater is an object of subclass extending the com.facebook.android.RequestListener class and overrides:

   //called on successful completion of the Request
   public void onComplete(final String response, final Object state){}

   // called if there is an error
   public void onFacebookError(FacebookError error){}

Refer to Android SDK documentation for more details.


Step 9: Social Channels

The Android SDK provides a method for displaying a Facebook Platform dialog, which allows you to enhance social distribution and provide basic Facebook functionality in your app with a singe line of code -- no need to build native dialogs, make API calls, or handle responses. Check out Mobile Distribution for up-to-date list of platforms supporting social distribution.

  • Feed Dialog - the dialog to publish posts to a user's feed.

To invoke a feed dialog:

    //post on user's wall.
    mFacebook.dialog(context, "feed", new PostDialogListener());
    
    //post on friend's wall.
    Bundle params = new Bundle();
    params.putString("to", "");
    mFacebook.dialog(context, "feed", params, new PostDialogListener());
  • Request Dialog - the dialog to send app requests to one or more friends. Note: incoming requests are not yet supported on Android and we will soon release a version of the Android app that supports requests, bookmarks, and search.

To invoke a request dialog:

    //Send requests with no friend pre-selected and user
    //selects friends on the dialog screen.
    mFacebook.dialog(context, "apprequests", new AppRequestsListener());
    
    //send request to a particular friend.
    Bundle params = new Bundle();
    params.putString("to", "");
    mFacebook.dialog(context, "apprequests", new AppRequestsListener());

Step 10: Timeline and Open Graph

Historically, Facebook has managed this graph and has expanded it over time as we launch new products (photos, places, etc.). In 2010, we extended the social graph, via the Open Graph protocol, to include 3rd party web sites and pages that people liked throughout the web. We are now extending the Open Graph to include arbitrary actions and objects created by 3rd party apps and enabling these apps to integrate deeply into the Facebook experience.

After a user adds your app to their Timeline, app specific actions are shared on Facebook via the Open Graph. As your app becomes an important part of how users express themselves, these actions are more prominently displayed throughout the Facebook Timeline and News Feed. This enables your app to become a key part of the user's and their friend's experience on Facebook.

Timeline is coming to mobile soon. In preparation, you can start integrating now.

To learn more about how you can integrate your app into Open Graph and Timeline, learn more or dive right into the tutorial.


Handle Errors:

Here's a few common errors and their solutions.

  • Build error: "missing gen files".

    This should go away when you rebuild the project. If you have trouble, try running Clean... from the Project menu.

  • Error: "invalid_key"

    This error means that the Facebook server doesn't recognize your Android key hash. Make sure that you correctly generated and copy/pasted your key hash into the Facebook developer settings console, and make sure that your application has been signed with the same key you registered with Facebook. Refer to Troubleshoot section below for further details.

  • Dialog won't load or shows a blank screen.

    If the logs don't give an indication of what's wrong, I suggest installing tcpdump on your device and getting a trace. Tutorial: http://www.vbsteven.be/blog/android-debugging-inspectin-network-traffic-with-tcpdump/

    If you still can't tell what's going on, then file an issue and please include the HTTP trace.

  • I can't upload photos with photos.upload.

    Make sure the Bundle value for the photo parameter is a byte array.


Tips:

  • You will need to have the Facebook application in your test environment. The SDK includes a developer release of the Facebook application that can be side-loaded for testing purposes. On an actual device, you can just download the latest version of the app from the Android Market, but on the emulator you will have to install it yourself:

  • Make sure to test both with and without the Facebook application. The SDK will fall back to a Webview if the Facebook app is not installed.

  • Use a signed build. You can sign with a debug key, but make sure that the key you used to sign matches the Key Hash field in the Facebook developer settings.

  • You can use this guide to developing on a device.


Troubleshoot:

  • Key Hash Reference DocSigning Your Applications.

  • Keytool command not found error: Keytool is provided by the standard Android SDK. if you get 'Command not found' error, you need to either add its path to your global 'PATH' or go to the folder to run this command. Standard location on Windows is C:\Program Files (x86)\Java\jdk1.6.0\bin and for MAC, its /usr/bin

  • Openssl: If you don't have openssl, install it from here: WindowsMAC. For Mac, follow the instructions here.

  • Invalid Key Hash: The keytool silently generates keyhash regardless of unknown debug.keystore location or wrong password. When running the sample app, use adb logcat to track errors. The error returned for invalid key is Facebook-authorize( 2631): Login failed: invalid_key. Visual indication of invalid keyhash is when SSO slides in and out of the Facebook app without prompting any screen or GDP dialog. If you get this error, 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 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 keyhash to the Developer App on Facebook.

    • If this all fails, try using cygwin or linux box to generate hashkey.

  • Installation [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES] error: Uninstall the app and try installing again.

  • onActivityResult() function is not called: Make sure 'Intent.FLAG_ACTIVITY_NO_HISTORY' is not defined for this intent in the AndroidManifest file.

  • App type Web vs Native/Desktop. Does it matter?: No, it does not matter. However it's recommended to use the type 'Native/Desktop' for your app.


Samples:

Hackbook for Android

The Hackbook for Android app includes Single Sign On implementation (SSO), sample API calls and advance features like Get new permissions, Run FQL Query, Graph API Explorer.

Open Graph Wishlist

The Wishlist for Mobile demonstrates the use of custom objects and actions on mobile platforms. It allows user to create a custom wishlist by adding product description and its image. User can also attach location to the item.