Android

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.

User Registration with Facebook Login App

Prerequisites

To complete this tutorial, you need:

Step 1 - Facebook Set up

To start using Facebook functions, you need to:

  1. Go to the Facebook Developer Website and create an account and an app.
  2. 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 at build.gradle (Module:app), add the following code in the dependencies{} section at build.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:
      1. At JitPack website paste parse-community:ParseFacebookUtils-Android in the Git repo URL box.
      2. 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.
    • 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..

  1. Go to your App dashboard at Back4App Website and click on Server Settings.
  2. Find the “Facebook Login” block and click on Settings. The “Facebook Login” block looks like this:
  3. 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 your facebook_app_id and paste it in the Facebook 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 the meta 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:

  1. 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;
    
  2. 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.

  3. 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()
     }
    
  4. 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()
     }
    
  5. If you want to associate an existing ParseUser to a Facebook account, you can link it like so:

    In the example project, this code is placed inside a LINK YOUR ACCOUNT TO FACEBOOK button callback.

  6. If you want to unlink Facebook from a user, simply do this:

    In the example project, this code is placed inside a UNLINK YOUR ACCOUNT FROM FACEBOOK button callback.

  7. It’s very important to use the following as a method outside the onCreate() method of your LoginActivity 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 the LoginActivity, don’t forget to change its Intent 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!