This post is about how to integrate Facebook login into an Android application.
The Facebook SDK
The Facebook SDK for Android enables people to sign into your app with Facebook Login. When people log into your app with Facebook they can grant permissions to your app so you can retrieve information or perform actions on Facebook on their behalf.
Follow the steps below to add Facebook Login to your app:
1 . Go to facebook developer site and log in using your Facebook account.
2 . After login, click on My Apps option shown at the top right.
3 . Now, select an app or create a new one.
4 . Choose Facebook Login Setup option from the left side and then click on Quickstart.
5 . Now, select the platform as Android.
6 . From the next screen, instead of downloading the Facebook SDK we will import it. Click on next.
Import the Facebook SDK
7 . Open Project-level build.gradle file and add the mavenCentral() repository to download the SDK from the Maven Central Repository:
buildscript {
repositories {
google()
mavenCentral()
}
8 . Open App-level build.gradle file and add the latest version of the SDK dependency under the dependencies section and then click on Sync Now.
dependencies {
implementation 'com.facebook.android:facebook-android-sdk:latest.release'
}
9 . Add the following statements to import the Facebook SDK packages.
import com.facebook.FacebookSdk;
import com.facebook.appevents.AppEventsLogger;
Add package and activity class name
10 . Enter your package name and default activity name with the fully qualified path and then click on save.
11 . The next window asks for setting up the key hashes. Run the provided commands on mac terminal/windows cmd and then add the generated hash key in the Key hashes field.
12 . Enable Single Sign-on for your app.
Edit Your Resources and Manifest
13 . Open your /app/res/values/strings.xml file and add the below string elements:
<resources>
<!--
On the Dashboard, navigate to Settings > Basic > App ID.
-->
<string name="facebook_app_id">1062987424533270</string>
<!--
same as facebook app id but prefix with fb
-->
<string name="fb_login_protocol_scheme">fb1062987424533270</string>
<!--
On the Dashboard, navigate to Settings > Advanced > Security > Client token.
-->
<string name="facebook_client_token">f946459314g319906e85bebb758ed5fe</string>
</resources>
14 . Open /app/manifest/AndroidManifest.xml file:
- Add meta-data elements to the application element for your app ID and client access token:
<application android:label="@string/app_name" ...>
...
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>
...
</application>
- Add an activity for Facebook, and an activity and intent filter for Chrome Custom Tabs inside your application element:
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
- Add a uses-permission element to the manifest above the application element:
<uses-permission android:name="android.permission.INTERNET" />
Creating the Layout File
The below layout file consist of a LoginButton from the Facebook SDK and two Textviews (to display the user name and email).
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/userName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@color/purple_500"
android:textSize="21sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/userEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:gravity="center"
android:textColor="@color/purple_500"
android:textSize="21sp"
app:layout_constraintEnd_toEndOf="@+id/userName"
app:layout_constraintStart_toStartOf="@+id/userName"
app:layout_constraintTop_toBottomOf="@+id/userName" />
<com.facebook.login.widget.LoginButton
android:id="@+id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:layout_marginBottom="30dp"
app:layout_constraintEnd_toEndOf="@+id/userEmail"
app:layout_constraintStart_toStartOf="@+id/userEmail"
app:layout_constraintTop_toBottomOf="@+id/userEmail" />
</androidx.constraintlayout.widget.ConstraintLayout>
Creating the MainActivity File
The MainActivity.kt file contains the below code:
MainActivity.kt
package com.c1ctech.floginexp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.facebook.login.LoginResult
import com.c1ctech.floginexp.databinding.ActivityMainBinding
import java.util.*
import android.content.Intent
import android.util.Log
import android.widget.Toast
import com.facebook.*
import org.json.JSONObject
import org.json.JSONException
import com.facebook.GraphResponse
import com.facebook.GraphRequest
class MainActivity : AppCompatActivity() {
lateinit var accessTokenTracker: AccessTokenTracker
lateinit var callbackManager: CallbackManager
lateinit var activityMainBinding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
// initializes the Facebook SDK
FacebookSdk.sdkInitialize(applicationContext)
setContentView(activityMainBinding.root)
// create an instance of callbackManager
// It manages the callbacks into the FacebookSdk from onActivityResult()'s method.
callbackManager = CallbackManager.Factory.create()
// set the permissions to use when the user logs in.
activityMainBinding.loginButton.setPermissions(listOf("email", "public_profile"))
// Registers a login callback to the given callback manager.
activityMainBinding.loginButton.registerCallback(
callbackManager,
object : FacebookCallback<LoginResult?> {
// called when the dialog completes without error.
override fun onSuccess(result: LoginResult?) {
Log.e("message: ", "success")
}
// called when the dialog is canceled.
override fun onCancel() {
Log.e("message: ", "onCancel")
}
// called when the dialog finishes with an error.
override fun onError(exception: FacebookException) {
Log.e("message: ", exception.localizedMessage)
}
})
accessTokenTracker = object : AccessTokenTracker() {
// The method that will be called with the access token changes.
override fun onCurrentAccessTokenChanged(
oldAccessToken: AccessToken?,
currentAccessToken: AccessToken?
) {
// condition is true when user logs out
if (currentAccessToken == null) {
activityMainBinding.userName.text = ""
activityMainBinding.userEmail.text = ""
Toast.makeText(this@MainActivity, "LogOut", Toast.LENGTH_SHORT).show()
} else {
//get user data from Json object and display it in textviews.
loadUserProfile(currentAccessToken)
}
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
callbackManager.onActivityResult(requestCode, resultCode, data)
super.onActivityResult(requestCode, resultCode, data)
}
override fun onDestroy() {
super.onDestroy()
// stops tracking the current access token
accessTokenTracker.stopTracking()
}
private fun loadUserProfile(currentAccessToken: AccessToken) {
// creates a new Request configured to retrieve a user's own profile.
val request = GraphRequest.newMeRequest(
currentAccessToken, object : GraphRequest.GraphJSONObjectCallback {
override fun onCompleted(`object`: JSONObject?, response: GraphResponse?) {
Log.d("TAG", `object`.toString())
try {
val first_name = `object`!!.getString("first_name")
val last_name = `object`!!.getString("last_name")
val email = `object`!!.getString("email")
activityMainBinding.userName.setText("$first_name $last_name")
activityMainBinding.userEmail.setText(email)
} catch (e: JSONException) {
e.printStackTrace()
}
}
})
val parameters = Bundle()
parameters.putString("fields", "first_name,last_name,email,id")
// set parameters for this request.
request.parameters = parameters
// Executes the request asynchronously.
request.executeAsync()
}
}
In the above code,
- sdkInitialize() method initializes the Facebook SDK.
- The instance of callbackManager manages the callbacks into the FacebookSdk from the Activity’s onActivityResult() method.
- The setPermissions() method sets the permissions to use when the user logs in.
- The registerCallback() method registers a login callback to the given callback manager.
- In onActivityResult() method, the callbackManager.onActivityResult() (returns true If the result could be handled) passes the login results to the registerCallback method via callbackManager.
- If login succeeds, the LoginResult parameter has the new AccessToken, and the most recently granted or declined permissions.
-
onCurrentAccessTokenChanged() method will be called with the access token changes.
- The Facebook Graph API is used to retrieve user info. It works by passing a Bundle of parameters as keys to the GraphRequest. The GraphRequest, on execution, should return the relevant info values based on the keys specified if they meet the permissions. The result is returned in the form of a JSON.
When you run the app you will see a login button on the screen:
When the user successfully logged in you will see the Log out button with user info and on-click of Log out button it will show dialog as shown below: