In this tutorial, we are going to learn how to integrate Facebook SDK for Android application login and also we will retrieve and display Facebook user profile information. Using the latest version of Facebook's SDK for Android, it takes only a few minutes to add this feature to your app.
To integrate Facebook login in your android application, Facebook account is an essential requirements.
Add Facebook SDK to your project
Step 1. Head over to Facebook Developer website to create your app and get your application ID by clicking on the Add a new app button.
Step 2. Go to Dashboard and click on Choose Platform tehn select Android as your platform from the window pop-up.
Step 3. The Facebook SDK is available on Maven Central. Add the Maven Central Repository to build.gradle (project):
repositories {
mavenCentral()
}
Step 4. Add compile 'com.facebook.android:facebook-android-sdk:[4,5)' to your build.gradle (module) dependencies.
Step 5. Open your strings.xml file and add a new string with the name facebook_app_id containing the value of your Facebook App ID
<string name="facebook_app_id">111</string>
Step 6. Open AndroidManifest.xml file and ddd a uses-permission element to the manifest
<uses-permission android:name="android.permission.INTERNET"/>
Step 7. Add a meta-data element to the application element
<application android:label="@string/app_name" ...>
...
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
...
</application>
Step 8. In the bottom form, enter the package name of your app and the name of your Activity.
Step 9. To fill in the Key Hashes field, open a terminal window and run the keytool command to generate a key hash using the debug keystore located at ~/.android/debug.keystore. This is what the command should look like.
# on MAC and any Linux OS keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
The default password for the debug keystore is android. Enter that password when prompted. The output of the command should be a string of 28 characters. Copy it, go back to your browser, and paste the string into the Key Hashes field.
Also you can get hash key using following snippet
public void getFacebookHashKey(Context context) {
try {
PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
String hashKey = new String(Base64.encode(md.digest(), 0));
Log.i(TAG, "getFacebookHashKey(): " + hashKey);
}
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "getFacebookHashKey()", e);
} catch (Exception e) {
Log.e(TAG, "getFacebookHashKey()", e);
}
}
Creating Login activity
Add two widgets to main_activity.xml file.
LoginButton to allow the user to log in to FacebookTextView to display the result of the latest login attemptYou can place them inside a RelativeLayout.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<com.facebook.login.widget.LoginButton
android:id="@+id/btnLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>
<TextView
android:id="@+id/tvStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
/>
</LinearLayout>
Now let's modify MainActivity activity. Remember that the name of this class and the package that it belongs to should match the values you entered while registering your app with Facebook.
Declare the widgets you defined in the activity's layout as fields of this class and declare a CallbackManager as another field.
private TextView tvStatus; private LoginButton btnLogin; private CallbackManager callbackManager;
The CallbackManager is used to manage the callbacks used in the app.
private CallbackManager callbackManager;
Next, initialize your instance of CallbackManager using the CallbackManager.Factory.create method.
callbackManager = CallbackManager.Factory.create();
Call setContentView to set the layout defined above as the layout of this Activity and then use findViewById to initialize the widgets.
setContentView(R.layout.main_activity);
tvStatus = (TextView) findViewById(R.id.tvStatus);
btnLogin = (LoginButton)findViewById(R.id.btnLogin);
tvStatus.setText("Status: ready");
It's time to create a callback to handle the results of the login attempts and register it with the CallbackManager. Custom callbacks should implement FacebookCallback. The interface has methods to handle each possible outcome of a login attempt:
onSuccess is called.onCancel is called.onError is called.To register the custom callback, use the registerCallback method.
When the onSuccess method is called, a LoginResult is passed as a parameter. Retrieve the access token it contains using getAccessToken and use its getUserId method to get the user's ID. To get the token in the form of a String, use getToken.
Tapping the login button starts off a new Activity, which returns a result. To receive and handle the result, override the onActivityResult method of your Activity and pass its parameters to the onActivityResult method of CallbackManager.
Below is full code of MainActivity.
public class MainActivity extends AppCompatActivity {
private TextView tvStatus;
private LoginButton btnLogin;
private CallbackManager callbackManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
callbackManager = CallbackManager.Factory.create();
setContentView(R.layout.activity_main);
tvStatus = (TextView) findViewById(R.id.tvStatus);
btnLogin = (LoginButton)findViewById(R.id.btnLogin);
tvStatus.setText("Status: ready");
btnLogin.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
AccessToken token = loginResult.getAccessToken();
tvStatus.setText(String.format("User ID: %s\n Auth Token: %s",
token.getUserId(), token.getToken()));
}
@Override
public void onCancel() {
tvStatus.setText("Status: Login attempt canceled.");
}
@Override
public void onError(FacebookException e) {
tvStatus.setText("Status: Login attempt failed.");
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
}
}
Creating Profile activity
Let's add some more code to get Profile and track it updates. Layout is the same.
public class MainActivity extends AppCompatActivity {
private TextView tvStatus;
private LoginButton btnLogin;
private CallbackManager callbackManager;
ProfileTracker profileTracker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
callbackManager = CallbackManager.Factory.create();
profileTracker = new ProfileTracker() {
@Override
protected void onCurrentProfileChanged(Profile oldProfile, Profile newProfile) {
updateProfileView(newProfile);
}
};
profileTracker.startTracking();
setContentView(R.layout.activity_main);
tvStatus = (TextView) findViewById(R.id.tvStatus);
btnLogin = (LoginButton)findViewById(R.id.btnLogin);
try {
Profile profile = Profile.getCurrentProfile();
updateProfileView(profile);
} catch (NullPointerException e) {
tvStatus.setText("Status: ready");
}
btnLogin.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
Profile profile = Profile.getCurrentProfile();
updateProfileView(profile);
}
@Override
public void onCancel() {
tvStatus.setText("Status: Login attempt canceled.");
}
@Override
public void onError(FacebookException e) {
tvStatus.setText("Status: Login attempt failed.");
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
}
protected void onStop() {
super.onStop();
profileTracker.stopTracking();
}
@Override
public void onResume() {
super.onResume();
Profile profile = Profile.getCurrentProfile();
updateProfileView(profile);
}
private void updateProfileView(Profile profile) {
if (profile != null) {
String status = String.format("Status: logged!\nUser: %s", profile.getName());
Log.d("DBG", profile.getProfilePictureUri(200,200).toString());
tvStatus.setText(status);
} else {
tvStatus.setText("Status: ready");
}
}
}
You can see screen of Activity in end of tutorial.
How to check login status and logout
You can check log in status usign following method
public boolean isLoggedIn() {
AccessToken accessToken = AccessToken.getCurrentAccessToken();
return accessToken != null;
}
For log out use following snippet
public void logOut() {
LoginManager.getInstance().logOut();
}
How to define custom login button
Define Button somewhere in layout
<Button
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="LOG IN WITH FACEBOOK"
android:layout_below="@id/vDivider"
android:layout_centerHorizontal="true"
android:onClick="logIn"/>
Snippet of MainActivity.java.
public class MainActivity extends AppCompatActivity {
private CallbackManager callbackManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// FACEBOOK LOGIN
callbackManager = CallbackManager.Factory.create();
if (isLoggedIn()) {
Profile profile = Profile.getCurrentProfile();
Log.d(Constants.TAG, profile.getFirstName());
}
}
public void logIn(View v) {
LoginManager.getInstance().logInWithReadPermissions(MainActivity.this, Arrays.asList("public_profile"));
LoginManager.getInstance().registerCallback(callbackManager,
new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
AccessToken token = loginResult.getAccessToken();
Toast.makeText(MainActivity.this, String.format("User ID: %s\n Auth Token: %s",
token.getUserId(), token.getToken()), Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel() {}
@Override
public void onError(FacebookException e) {
Log.d(Constants.TAG, e.toString());
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
}
}
The logInWithPermissionName methods always open a UI and prompt someone for additional permissions if needed. To get addiitional permissions from someone, make this request with the Facebook SDK for Android:
LoginManager.getInstance().logInWithReadPermissions(
MainActivity.this,
Arrays.asList("email"));
How to get user profile
After login you can get basic user profile using
Profile profile = Profile.getCurrentProfile(); Log.d(Constants.TAG, profile.getName()); Log.d(Constants.TAG, profile.getUri(200, 200));
Also you can use Graph API to get additional information
GraphRequest request = GraphRequest.newMeRequest(
AccessToken.getCurrentAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
@Override
public void onCompleted(JSONObject object, GraphResponse response) {
Log.d(Constants.TAG, object.toString());
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,link,email,gender,birthday,work");
request.setParameters(parameters);
request.executeAsync();
Creating Share activity
In this example we'll implement sharing from your Android app to Facebook. When someone shares from your app, their content appears on their Timeline and may appear in their friends' News Feeds.
First, you need to set up a ContentProvider in your AndroidManifest.xml where 111 is your app ID. Add it before </application>
<provider android:authorities="com.facebook.app.FacebookContentProvider111"
android:name="com.facebook.FacebookContentProvider"
android:exported="true"/>
When people share links from your app to Facebook, it includes attributes that show up in the post:
contentURL, the link to be sharedcontentTitle that represents the title of the content in the link (deprecated)imageURL, the URL of thumbnail image that will appear on the post (deprecated)contentDescription of the content, usually 2-4 sentences (deprecated)
ShareLinkContent linkContent = new ShareLinkContent.Builder()
.setContentUrl(Uri.parse("http://en.proft.me"))
.build();
ShareDialog dlgShare = new ShareDialog(getActivity());
dlgShare.show(linkContent);
You can debug share link at Sharing Debugger.
People can share photos from your app to Facebook with the ShareDialog or with a custom interface.
If you want to share photo you must request more permissions when declare LoginButton like this
btnLogin.setReadPermissions("email,publish_actions");
Build your share content for photos into the SharePhotoContent model. For a list of all attributes, see SharePhotoContent reference.
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
SharePhoto photo = new SharePhoto.Builder()
.setBitmap(icon)
.setCaption("Android icon")
.build();
SharePhotoContent content = new SharePhotoContent.Builder()
.addPhoto(photo)
.build();
dlgShare.show(content);
The Like button is a quick way for people to share content with their friends. A tap on the Like button will like pieces of content from your app and share them on Facebook. The Like button can be used to like a Facebook Page or any Open Graph object and can be referenced by URL or ID. To add a Like button add the following code snippet to your view:
btnLike = (LikeView) findViewById(R.id.btnLike);
btnLike.setObjectIdAndType("http://en.proft.me", LikeView.ObjectType.PAGE);
Full activity_main.xml layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<com.facebook.login.widget.LoginButton
android:id="@+id/btnLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
<TextView
android:id="@+id/tvStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"/>
<Button
android:id="@+id/btnShareLink"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="Share link"
android:onClick="shareLink" />
<Button
android:id="@+id/btnShareImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="Share image"
android:onClick="shareImage"/>
<com.facebook.share.widget.LikeView
android:id="@+id/btnLike"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
</LinearLayout>
Full code of MainActivity
public class MainActivity extends AppCompatActivity {
private TextView tvStatus;
private LoginButton btnLogin;
private CallbackManager callbackManager;
ProfileTracker profileTracker;
Button btnShareLink, btnShareImage;
LikeView btnLike;
ShareDialog dlgShare;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
callbackManager = CallbackManager.Factory.create();
profileTracker = new ProfileTracker() {
@Override
protected void onCurrentProfileChanged(Profile oldProfile, Profile newProfile) {
updateProfileView(newProfile);
}
};
profileTracker.startTracking();
setContentView(R.layout.activity_main);
dlgShare = new ShareDialog(this);
tvStatus = (TextView) findViewById(R.id.tvStatus);
btnLogin = (LoginButton)findViewById(R.id.btnLogin);
btnShareLink = (Button) findViewById(R.id.btnShareLink);
btnShareImage = (Button) findViewById(R.id.btnShareImage);
btnLike = (LikeView) findViewById(R.id.btnLike);
btnLike.setObjectIdAndType("http://en.proft.me", LikeView.ObjectType.PAGE);
try {
Profile profile = Profile.getCurrentProfile();
updateProfileView(profile);
} catch (NullPointerException e) {
tvStatus.setText("Status: ready");
}
dlgShare.registerCallback(callbackManager, new FacebookCallback<Sharer.Result>() {
@Override
public void onSuccess(Sharer.Result result) {
Toast.makeText(MainActivity.this, "Successfully shared", Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel() {
Toast.makeText(MainActivity.this, "Sharing cancelled", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(FacebookException e) {
Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
//
// LOGIN callback
//
btnLogin.setReadPermissions("email,publish_actions");
btnLogin.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
Profile profile = Profile.getCurrentProfile();
updateProfileView(profile);
}
@Override
public void onCancel() {
tvStatus.setText("Status: Login attempt canceled.");
}
@Override
public void onError(FacebookException e) {
tvStatus.setText("Status: Login attempt failed.");
}
});
//
// SHARE LINK callback
//
btnShareLink.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ShareDialog.canShow(ShareLinkContent.class)) {
ShareLinkContent linkContent = new ShareLinkContent.Builder()
.setContentUrl(Uri.parse("http://en.proft.me"))
.setContentTitle("Proft blog")
.setImageUrl(Uri.parse("http://en.proft.me/static/img/melogo.png"))
.setContentDescription("Test message from Android.")
.build();
dlgShare.show(linkContent);
}
}
});
//
// SHARE IMAGE callback
//
btnShareImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ShareDialog.canShow(SharePhotoContent.class)) {
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
SharePhoto photo = new SharePhoto.Builder()
.setBitmap(icon)
.setCaption("My caption")
.build();
SharePhotoContent content = new SharePhotoContent.Builder()
.addPhoto(photo)
.build();
dlgShare.show(content);
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
callbackManager.onActivityResult(requestCode, resultCode, data);
}
protected void onStop() {
super.onStop();
profileTracker.stopTracking();
}
@Override
public void onResume() {
super.onResume();
Profile profile = Profile.getCurrentProfile();
updateProfileView(profile);
}
private void updateProfileView(Profile profile) {
if (profile != null) {
String status = String.format("Status: logged!\nUser: %s", profile.getName());
Log.d("VVV", profile.getProfilePictureUri(200,200).toString());
tvStatus.setText(status);
btnShareLink.setVisibility(View.VISIBLE);
btnShareImage.setVisibility(View.VISIBLE);
btnLike.setVisibility(View.VISIBLE);
} else {
tvStatus.setText("Status: ready");
btnShareLink.setVisibility(View.GONE);
btnShareImage.setVisibility(View.GONE);
btnLike.setVisibility(View.GONE);
}
}
}
Result
How to get user's photos
To request user's photos I'm going to use Graph API. The Android SDK has support for integrating with Facebook Graph API. With the GraphRequest and GraphResponse classes, you can make requests and get responses in JSON asynchronously.
First of all we need clasess for deserialization list of photos and one photo with url.
File FacebookResponsePhotos.java
class FacebookResponsePhotos {
class Photo {
String created_time;
String id;
}
class Cursors {
String before;
String after;
}
class Paging {
Cursors cursors;
}
public List<Photo> data;
public Paging paging;
public List<Photo> getPhotos() {
return data;
}
}
File FacebookResponsePhoto.java
class FacebookResponsePhoto {
class Image {
int height;
int width;
String source;
}
public List<Image> images;
public String id;
public List<Image> getImages() {
return images;
}
public String getHeight960() {
String url = "";
if (images.size() > 0) {
for(Image img : images){
if(img.height == 960) {
url = img.source;
break;
}
}
}
return url;
}
}
Second we need permission for user_photos.
btnLogin = (LoginButton)findViewById(R.id.btnLogin);
btnLogin.setReadPermissions("public_profile,user_photos");
After successful login we can use following method to get list of photos and one photo with url
public void getUserPhotos() {
new GraphRequest(AccessToken.getCurrentAccessToken(), "/me/photos", null, HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
Log.d(Constants.TAG, "PHOTOS " + response.getJSONObject().toString());
FacebookResponsePhotos fbResponse = new Gson().fromJson(
response.getJSONObject().toString(), FacebookResponsePhotos.class);
for (FacebookResponsePhotos.Photo p : fbResponse.getPhotos()) {
getPhotoUrl(p.id);
}
}
}
).executeAsync();
}
public void getPhotoUrl(String photoID) {
new GraphRequest(AccessToken.getCurrentAccessToken(), "/" + photoID + "?fields=images", null, HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
Log.d(Constants.TAG, "PHOTO " + response.getJSONObject().toString());
FacebookResponsePhoto fbResponse = new Gson().fromJson(
response.getJSONObject().toString(), FacebookResponsePhoto.class);
Log.d(TAG, "onCompleted URL: " + fbResponse.getHeight960());
}
}
).executeAsync();
}