How to add Facebook login to your Android App
Introduction
In this guide, you will learn how to login using Facebook Login and Parse User
class through Back4App. This tutorial uses a basic app created in Android Studio 4.1.1 with buildToolsVersion=30.0.3
, Compile SDK Version = 30
and targetSdkVersion 30
At any time, you can access the complete Project via our GitHub repositories.
Goal
Create a Login with Facebook feature to your Android App using Parse and Back4App.
Prerequisites
To complete this tutorial, you need:
- Android Studio.
- An app created on Back4App.
- Note: Follow the New Parse App Tutorial to learn how to create a Parse App on Back4App.
- An android app connected to Back4app.
- Note: Follow the Install Parse SDK Tutorial to create an Android Studio Project connected to Back4App.
- A device (or virtual device) running Android 4.1 (Jelly Bean) or newer.
Step 1 - Facebook Set up
To start using Facebook functions, you need to:
- Go to the Facebook Developer Website and create an account and an app.
- Follow Facebook’s Quickstart Guide by clicking here and pay attention to the following recommendations:
Here are the steps included in Facebook’s Quickstart Guide, which you need to follow carefully, as you are not going to follow them precisely as Facebook suggests:
- In Step 3, instead of adding
1
implementation 'com.facebook.android:facebook-login:[8.1)'
in the
dependencies{}
section atbuild.gradle (Module:app)
, add the following code in thedependencies{}
section atbuild.gradle (Module:app)
:1 2 3
// update the versions to the latest ones implementation "com.github.parse-community:ParseFacebookUtils-Android:latest.version.here" implementation 'com.facebook.android:facebook-android-sdk:latest.version.here'
- Remember to update the version of Parse Facebook Utils SDK for Android to the latest one. You can find out which is the latest version at the JitPack website, following these steps:
- At JitPack website paste
parse-community:ParseFacebookUtils-Android
in theGit repo URL
box. - After doing that, click on the
Look up
button. Then you should see the available versions of Parse SDK for Android, as shown in the following image.
- At JitPack website paste
- In Step 4, you’ll be asked to add internet permission at the
application
element in/app/manifest/AndroidManifest.xml
file, but you have already added it while following Install Parse SDK Tutorial so you don’t need to do this. - In Step 6, you’ll need to provide key hashes, so you must have Open SSL installed. Facebook’s Guide doesn’t provide command lines to generate key hashes in Linux, but doing that is simple, as all it requires from you is to open a terminal window and run the following command:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
- Don’t follow the steps of Facebook’s Quickstart Guide right after Step 6.
What is SHA-1 (Secure Hashing Algorithm)
SHA-1, called the Secure Hashing Algorithm, is the most common encryption algorithm. SHA-1, designed by United States National Security Agency. SHA-1 fingerprint is a unique key generated for your PC that can be used for signing. Its mainly used for submitting for using the some APIs (Like the Facebook api we will use in this guide.). If you want to learn more details, you can visit the SHA-1 Wikipedia page.You should follow the other steps described on Facebook’s Quickstart Guide and not mentioned here..
- In Step 3, instead of adding
Step 2 - Link your Facebook App with Back4App
- Go to your App dashboard at Back4App Website and click on
Server Settings
. - Find the “Facebook Login” block and click on
Settings
. The “Facebook Login” block looks like this: - We need to add our facebook_id, which we got from Facebook Guide to string.xml(You should have followed the Facebook Guide and did this before). Go to your Android Studio Project, open your strings file:
.../app/src/main/res/values/strings.xml
, copy yourfacebook_app_id
and paste it in theFacebook appId
field of the last page of Back4App that you opened. Lastly, press the+
button.Step 3 - Add provider element in the Manifest file
Go back to your Android Studio Project and inside the
application
element in/app/manifest/AndroidManifest.xml
file, right after themeta data
element, add the following code.
1
2
3
4
5
<provider
android:name="com.facebook.FacebookContentProvider"
<!--don't forget to put your Facebook App ID in the following link-->
android:authorities="com.facebook.app.FacebookContentProviderYOUR_FACEBOOK_APP_ID"
android:exported="true" />
Don’t forget to put your Facebook App ID in the code above.
Step 4 - Initialize Parse Facebook Util SDKs
In your Android Studio Project, in the Java file called App
that extends Application that you created to initialize the Parse SDK, on its onCreate
method, right after Parse.initialize()
call, use the following code to initialize Parse Facebook Utils SDK.
1
ParseFacebookUtils.initialize(this);
If you don’t have an
App.java
file as described in this step, access the Install Parse SDK for Android documentation and make sure that you have followed all the steps required to install Parse SDK correctly. If you do not install Parse SDK properly your facebook login with Parse will not work.
Step 5 - Set up
At the beginning of each Parse activity, import the following:
1
2
3
4
5
6
7
8
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import com.facebook.login.LoginManager;
import com.parse.ParseUser;
Step 6 - Log In
To implement your Login Activity, do the following:
- Import into your
LoginActivity
, in addition to the dependencies imported in Step 4:1 2 3 4 5 6 7 8 9 10 11 12 13 14
import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.widget.Button; import android.widget.Toast; import com.facebook.AccessToken; import com.facebook.GraphRequest; import com.parse.ParseUser; import com.parse.facebook.ParseFacebookUtils; import org.json.JSONException; import java.util.Arrays; import java.util.Collection;
-
To implement Facebook Login, simply use the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
final ProgressDialog dialog = new ProgressDialog(this); dialog.setTitle("Please, wait a moment."); dialog.setMessage("Logging in..."); dialog.show(); Collection<String> permissions = Arrays.asList("public_profile", "email"); ParseFacebookUtils.logInWithReadPermissionsInBackground(this, permissions, (user, err) -> { dialog.dismiss(); if (err != null) { Log.e("FacebookLoginExample", "done: ", err); Toast.makeText(this, err.getMessage(), Toast.LENGTH_LONG).show(); } else if (user == null) { Toast.makeText(this, "The user cancelled the Facebook login.", Toast.LENGTH_LONG).show(); Log.d("FacebookLoginExample", "Uh oh. The user cancelled the Facebook login."); } else if (user.isNew()) { Toast.makeText(this, "User signed up and logged in through Facebook.", Toast.LENGTH_LONG).show(); Log.d("FacebookLoginExample", "User signed up and logged in through Facebook!"); getUserDetailFromFB(); } else { Toast.makeText(this, "User logged in through Facebook.", Toast.LENGTH_LONG).show(); Log.d("FacebookLoginExample", "User logged in through Facebook!"); showAlert("Oh, you!", "Welcome back!"); } });
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
val dlg = ProgressDialog(this) dlg.setTitle("Please, wait a moment.") dlg.setMessage("Logging in...") dlg.show() val permissions: Collection<String> = listOf("public_profile", "email") ParseFacebookUtils.logInWithReadPermissionsInBackground(this, permissions) { user: ParseUser?, err: ParseException? -> dlg.dismiss() when { err != null -> { Log.e("FacebookLoginExample", "done: ", err) Toast.makeText(this, err.message, Toast.LENGTH_LONG).show() } user == null -> { Toast.makeText(this, "The user cancelled the Facebook login.", Toast.LENGTH_LONG).show() Log.d("FacebookLoginExample", "Uh oh. The user cancelled the Facebook login.") } user.isNew -> { Toast.makeText(this, "User signed up and logged in through Facebook.", Toast.LENGTH_LONG).show() Log.d("FacebookLoginExample", "User signed up and logged in through Facebook!") getUserDetailFromFB() } else -> { Toast.makeText(this, "User logged in through Facebook.", Toast.LENGTH_LONG).show() Log.d("FacebookLoginExample", "User logged in through Facebook!") showAlert("Oh, you!", "Welcome back!") } } }
In the example project, this code is placed inside a
LOGIN VIA FACEBOOK
button callback. -
After a successful login through Facebook to our App, we can now get some basic logged user information.. As you can see, there are many more methods included in the code above. The
getUserDetailFromFB
method is responsible for fetching user details. Here’s the code for this method:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
private void getUserDetailFromFB() { GraphRequest request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken(), (object, response) -> { ParseUser user = ParseUser.getCurrentUser(); try { if (object.has("name")) user.setUsername(object.getString("name")); if (object.has("email")) user.setEmail(object.getString("email")); } catch (JSONException e) { e.printStackTrace(); } user.saveInBackground(e -> { if (e == null) { showAlert("First Time Login!", "Welcome!"); } else showAlert("Error", e.getMessage()); }); }); Bundle parameters = new Bundle(); parameters.putString("fields", "name,email"); request.setParameters(parameters); request.executeAsync(); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
private fun getUserDetailFromFB() { val request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken()) { `object`: JSONObject, _: GraphResponse? -> val user = ParseUser.getCurrentUser() try { user.username = `object`.getString("name") } catch (e: JSONException) { e.printStackTrace() } try { user.email = `object`.getString("email") } catch (e: JSONException) { e.printStackTrace() } user.saveInBackground { if (it == null) showAlert("First Time Login!", "Welcome!") else showAlert("Error", it.message) } } val parameters = Bundle() parameters.putString("fields", "name,email") request.parameters = parameters request.executeAsync() }
-
It’s interesting to add a method to display Alert Dialogs and make the process look more professional. In this function, we also get a user parameter. When going to the MainAtivity page, we send this user parameter in the intent, and in the MainActivity, we pull the information in this user and print it on the screen. The method below does this:
1 2 3 4 5 6 7 8 9 10 11 12 13
private void showAlert(String title, String message) { AlertDialog.Builder builder = new AlertDialog.Builder(this) .setTitle(title) .setMessage(message) .setPositiveButton("OK", (dialog, which) -> { dialog.cancel(); Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }); AlertDialog ok = builder.create(); ok.show(); }
1 2 3 4 5 6 7 8 9 10 11 12 13
private fun showAlert(title: String, message: String?) { val builder = AlertDialog.Builder(this) .setTitle(title) .setMessage(message) .setPositiveButton("OK") { dialog: DialogInterface, which: Int -> dialog.cancel() val intent = Intent(this@LoginActivity, MainActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) } val ok = builder.create() ok.show() }
- If you want to associate an existing ParseUser to a Facebook account, you can link it like so:
1 2 3 4 5 6 7 8 9 10 11
Collection<String> permissions = Arrays.asList("public_profile", "email"); if (!ParseFacebookUtils.isLinked(ParseUser.getCurrentUser())) { ParseFacebookUtils.linkWithReadPermissionsInBackground(ParseUser.getCurrentUser(), this, permissions, ex -> { if (ParseFacebookUtils.isLinked(ParseUser.getCurrentUser())) { Toast.makeText(this, "Woohoo, user logged in with Facebook.", Toast.LENGTH_LONG).show(); Log.d("FacebookLoginExample", "Woohoo, user logged in with Facebook!"); } }); } else { Toast.makeText(this, "You have already linked your account with Facebook.", Toast.LENGTH_LONG).show(); }
1 2 3 4 5 6 7 8 9 10 11 12
val permissions= listOf("public_profile","email") if (!ParseFacebookUtils.isLinked(ParseUser.getCurrentUser())){ ParseFacebookUtils.linkWithReadPermissionsInBackground(ParseUser.getCurrentUser(),this,permissions) { if (ParseFacebookUtils.isLinked(ParseUser.getCurrentUser())){ Toast.makeText(this, "Woohoo, user logged in with Facebook.", Toast.LENGTH_LONG).show() Log.d("FacebookLoginExample", "Woohoo, user logged in with Facebook!") } } } else { Toast.makeText(this, "You have already linked your account with Facebook.", Toast.LENGTH_LONG).show() } }
In the example project, this code is placed inside a
LINK YOUR ACCOUNT TO FACEBOOK
button callback. - If you want to unlink Facebook from a user, simply do this:
1 2 3 4 5 6 7 8
ParseFacebookUtils.unlinkInBackground(ParseUser.getCurrentUser(), ex -> { if (ex == null) { Toast.makeText(this, "The user is no longer associated with their Facebook account.", Toast.LENGTH_LONG).show(); Log.d("MyApp", "The user is no longer associated with their Facebook account."); } else { Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show(); } });
1 2 3 4 5 6 7 8
ParseFacebookUtils.unlinkInBackground(ParseUser.getCurrentUser()) { if (it == null) { Toast.makeText(this,"The user is no longer associated with their Facebook account.",Toast.LENGTH_LONG).show() Log.d("MyApp", "The user is no longer associated with their Facebook account.") } else { Toast.makeText(this, it.message, Toast.LENGTH_LONG).show() } }
In the example project, this code is placed inside a
UNLINK YOUR ACCOUNT FROM FACEBOOK
button callback. - It’s very important to use the following as a method outside the
onCreate()
method of yourLoginActivity
to pass login results to the LoginManager via callbackManager and avoid errors.1 2 3 4 5
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); ParseFacebookUtils.onActivityResult(requestCode, resultCode, data); }
1 2 3 4
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) ParseFacebookUtils.onActivityResult(requestCode, resultCode, data) }
Step 7 - Log out
To implement Facebook Logout, simply use the code mentioned below:
1
2
3
4
5
6
7
8
9
10
11
final ProgressDialog dialog = new ProgressDialog(this);
dialog.setTitle("Please, wait a moment.");
dialog.setMessage("Logging out...");
dialog.show();
LoginManager.getInstance().logOut();
ParseUser.logOutInBackground(e -> {
if (e == null)
showAlert("So, you're going...", "Ok...Bye-bye then", true);
else
showAlert("Error...", e.getMessage(), false);
});
1
2
3
4
5
6
7
8
9
10
11
val dlg = ProgressDialog(this)
dlg.setTitle("Please, wait a moment.")
dlg.setMessage("Logging out...")
dlg.show()
LoginManager.getInstance().logOut()
ParseUser.logOutInBackground { e->
if (e == null)
showAlert("So, you're going...", "Ok...Bye-bye then", true)
else
showAlert("Error...", e.message, false)
}
In the example project, this code is placed inside a
LOG OUT
button callback.
The method
alertDisplayer
is the same that you added in theLoginActivity
, don’t forget to change itsIntent
arguments though.
It’s done!
At this stage, you can log in, register and log out of your app with Facebook using Parse Server core features through Back4App!