54

I''m following this Tutorial but so far I can't make it work, though this is from a year ago or so...

I'm using androidStudo 1.2.2 and FacebookSDK 4.

I want a simple login into facebook using a custom button, like the one shown in this image:

Example

Now, in the example from the tutorial I'm having problems with the Session variable, it says it cannot resolve it, neither getActivity()

Has naybody tried this on FacebookSDK4.0?

Is that a correct approach or maybe there is something more updated?

3
  • 1
    Session is removed in new facebook sdk. you can't use Session or UiLifecycleHelper with new facebook sdk. Commented Jul 11, 2015 at 5:04
  • 1
    Check the 2nd answer below, I believe the selected answer is not 100% correct
    – Shehabic
    Commented Aug 21, 2016 at 15:40
  • The tutorial link is outdated.
    – Jeff T.
    Commented May 21, 2018 at 12:50

8 Answers 8

170

Step 1: First add FrameLayout and make facebook button visibility="gone" and add your custom button. Don't forgot to put xmlns:facebook="http://schemas.android.com/apk/res-auto" in your main layout.

<FrameLayout
        android:id="@+id/FrameLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <com.facebook.login.widget.LoginButton
            android:id="@+id/login_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone" />

        <Button
            android:id="@+id/fb"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="#416BC1"
            android:onClick="onClick"
            android:text="FaceBook"
            android:textColor="#ffffff"
            android:textStyle="bold" />
    </FrameLayout>

Step 2: Initialize FacebookSdk in onCreate before inflecting layout.

FacebookSdk.sdkInitialize(this.getApplicationContext());

Step 3: add this into your java file.

callbackManager = CallbackManager.Factory.create();

fb = (Button) findViewById(R.id.fb);
loginButton = (LoginButton) findViewById(R.id.login_button);

List < String > permissionNeeds = Arrays.asList("user_photos", "email",
    "user_birthday", "public_profile", "AccessToken");
loginButton.registerCallback(callbackManager,
new FacebookCallback < LoginResult > () {@Override
    public void onSuccess(LoginResult loginResult) {

        System.out.println("onSuccess");

        String accessToken = loginResult.getAccessToken()
            .getToken();
        Log.i("accessToken", accessToken);

        GraphRequest request = GraphRequest.newMeRequest(
        loginResult.getAccessToken(),
        new GraphRequest.GraphJSONObjectCallback() {@Override
            public void onCompleted(JSONObject object,
            GraphResponse response) {

                Log.i("LoginActivity",
                response.toString());
                try {
                    id = object.getString("id");
                    try {
                        URL profile_pic = new URL(
                            "http://graph.facebook.com/" + id + "/picture?type=large");
                        Log.i("profile_pic",
                        profile_pic + "");

                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
                    name = object.getString("name");
                    email = object.getString("email");
                    gender = object.getString("gender");
                    birthday = object.getString("birthday");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
        Bundle parameters = new Bundle();
        parameters.putString("fields",
            "id,name,email,gender, birthday");
        request.setParameters(parameters);
        request.executeAsync();
    }

    @Override
    public void onCancel() {
        System.out.println("onCancel");
    }

    @Override
    public void onError(FacebookException exception) {
        System.out.println("onError");
        Log.v("LoginActivity", exception.getCause().toString());
    }
});

Step 4: Don't forget to add following code.

@Override
protected void onActivityResult(int requestCode, int responseCode,
Intent data) {
    super.onActivityResult(requestCode, responseCode, data);
    callbackManager.onActivityResult(requestCode, responseCode, data);
}

Step 5: Set your custom button click to FacebookLogin button click.

public void onClick(View v) {
    if (v == fb) {
        loginButton.performClick();
    }
 }

Step 6: For programmatically logout use this.

LoginManager.getInstance().logOut();

Step 7: you can find user logged in or not by profile.

profile = Profile.getCurrentProfile().getCurrentProfile();
if (profile != null) {
    // user has logged in
} else {
    // user has not logged in
}
16
  • 2
    Super awesome! I'm implementing it, I just have an error on this line: 'loginButton.registerCallback(callbackManager,' 'Cannot resolve method' :( Is there something missing?
    – NeoVe
    Commented Jul 11, 2015 at 0:05
  • 2
    I'm going to open a new question for the error, thank you very much.
    – NeoVe
    Commented Jul 12, 2015 at 0:24
  • 2
    its good .. can give example how to make custom logout button for this .
    – Vishal
    Commented Jun 15, 2016 at 13:22
  • 2
    Thank you very much, this post is very helpful... Perfectly explained Commented Jan 5, 2017 at 10:00
  • 2
    loginButton.performClick(); this is the meat of the answer, thanks buddy :) Commented Dec 12, 2017 at 18:16
104

IMO part of the selected answer is kind of work-around not the proper solution. So what needs to be changed to make it proper is the following:

  1. Get rid of "com.facebook.login.widget.LoginButton" from your XML

    <com.facebook.login.widget.LoginButton
            android:id="@+id/login_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone" />
    
  2. Get rid of all references to the "LoginButton" in your Java code

  3. Use Facebook's "LoginManager" class which is there for that purpose as follows:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Some code
        callbackManager = CallbackManager.Factory.create();
        LoginManager.getInstance().registerCallback(
            callbackManager,
            new FacebookCallback < LoginResult > () {
                @Override
                public void onSuccess(LoginResult loginResult) {
                    // Handle success
                }
    
                @Override
                public void onCancel() {
                }
    
                @Override
                public void onError(FacebookException exception) {
                } 
           }
       );
    }
    
    public void onClick(View v) {
       if (v == fb) {
           LoginManager.getInstance().logInWithReadPermissions(
               this,
               Arrays.asList("user_photos", "email", "user_birthday", "public_profile")
           );
       }
    }
    
    // this part was missing thanks to wesely
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        callbackManager.onActivityResult(requestCode, resultCode, data);
    }
    
10
  • 1
    Hi @Shehabix, this was years ago, but I'll check your code ASAP and write back! Promise! Indeed, the other answer it wasn't a definitive solution
    – NeoVe
    Commented Aug 21, 2016 at 19:39
  • 1
    That's a clean solution. Much better, than that accepted answer-workaround.
    – ViliusK
    Commented Nov 30, 2016 at 14:32
  • 1
    Also, you might want to update button's label from Log in to Log out depending on LoginManager's state.
    – ViliusK
    Commented Nov 30, 2016 at 14:33
  • 10
    It should be the ACCEPTED answer as it provides a clean and legal way of maneuvering the login button.
    – aB9
    Commented Jan 28, 2017 at 20:42
  • 1
    ACCEPTED answer!
    – Asad
    Commented Sep 2, 2018 at 15:41
16

This is very simple. Add a button in the layout file like

<Button
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:text="Login with facebook"
    android:textColor="#ffff"
    android:layout_gravity="center"
    android:textStyle="bold"
    android:onClick="fbLogin"
    android:background="@color/colorPrimary"/>

And in the onClick place the LoginManager's registercallback() method Becuse the this method automatically executes.

like:

  public void fbLogin(View view)
{
    // Before Edit:
    // LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("user_photos", "email", "public_profile", "user_posts" , "AccessToken"));

    LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("user_photos", "email", "public_profile", "user_posts"));
    LoginManager.getInstance().logInWithPublishPermissions(this, Arrays.asList("publish_actions"));
    LoginManager.getInstance().registerCallback(callbackManager,
            new FacebookCallback<LoginResult>()
            {
                @Override
                public void onSuccess(LoginResult loginResult)
                {
                    // App code
                }

                @Override
                public void onCancel()
                {
                    // App code
                }

                @Override
                public void onError(FacebookException exception)
                {
                    // App code
                }
            });
}

Have Fun

13

(don't have enough reputation to add a comment ...)

I tried the @Shehabix's answer, can't receive callback until I add this

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

then it works fine.

1
  • 2
    I will update my answer with this part later tonight, thanks
    – Shehabic
    Commented Sep 27, 2016 at 7:07
10

The Simple answer is add facebookButton.performClick() inside cutomBtn.setOnClickListener

    <!-- connect with Facebook -->
    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <com.facebook.login.widget.LoginButton
            android:id="@+id/fb_connect"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:textSize="@dimen/login_fb_font_size"
            android:visibility="invisible" />

        <LinearLayout
            android:id="@+id/mfb_connect"
            style="@style/facebook_button">

            <ImageView
                style="@style/login_connect_icon"
                android:src="@drawable/ic_facebook" />

            <TextView
                style="@style/login_connect_text"
                android:text="@string/login_connect_facebook" />
        </LinearLayout>
    </RelativeLayout>

...

private LoginButton fb_connect;
private LinearLayout mfb_connect;

...

    // the button from facebook sdk
    fb_connect = (LoginButton) findViewById(R.id.fb_connect);
    // handle the click from my custom button to perfrom action click on facebook sdk button
    mfb_connect = (LinearLayout) findViewById(R.id.mfb_connect);
    mfb_connect.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            fb_connect.performClick();
        }
    });

That will achieve this:

enter image description here

1
  • 2
    Really helpful :) Commented Jan 29, 2018 at 19:32
2

i just call the facebook default button from my custom button and left every single line of code as documented. and bang it works successfully.

public class SignInFragment extends Fragment implements
   FragmentChangeListener{
   private Button facebook



    private FirebaseAuth firebaseAuth;
    private CallbackManager mCallBackManager;
    private LoginButton loginButton;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View view =  inflater.inflate(R.layout.fragment_sign_in, container, false);

        facebook = view.findViewById(R.id.facebookButton);
        loginButton = view.findViewById(R.id.facebookBtn);

        firebaseAuth = FirebaseAuth.getInstance();

        facebook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loginButton.callOnClick();
            }
        });

        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCallBackManager = CallbackManager.Factory.create();
                loginButton.setFragment(SignInFragment.this);
                loginButton.setPermissions("email","public_profile");
                loginButton.registerCallback(mCallBackManager, new FacebookCallback<LoginResult>() {
                    @Override
                    public void onSuccess(LoginResult loginResult) {
                        handleFacebookAccessToken(loginResult.getAccessToken());
                    }

                    @Override
                    public void onCancel() {
                        Toast.makeText(getContext(),"Is Cancelled",Toast.LENGTH_LONG).show();
                    }

                    @Override
                    public void onError(FacebookException error) {
                        Toast.makeText(getContext(),error.getMessage(),Toast.LENGTH_LONG).show();
                    }
                });
            }
        });

        return view;
    }


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

        mCallBackManager.onActivityResult(requestCode, resultCode, data);
      
    }

    private void handleFacebookAccessToken(AccessToken token) {
        AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
        firebaseAuth.signInWithCredential(credential)
                .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            FirebaseUser user = firebaseAuth.getCurrentUser();
                            startActivity(new Intent(getContext(),MainActivity.class));
                        } else {
                            // If sign in fails, display a message to the user.
                            Toast.makeText(getContext(), task.getException().getMessage(),
                                    Toast.LENGTH_SHORT).show();
                        }

                    }
                });
    } 
 }
1
  • 1
    This worked for me perfectly in fragment. i just called the Default Facebook login button which i kept Visibility GONE in my XML from my custom button. Commented May 26, 2020 at 16:04
1

Complementing the answers by Harvi and Shehabix, I would suggest to add this method as this registers the authentication in Firebase Auth.

This method should be called inside "On Success" of LoginManager.

private void handleFacebookAccessToken(AccessToken token) {

    AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {

                        //Toast.makeText(MainActivity.this, "Autenticando",Toast.LENGTH_SHORT).show();

                    } else {
                        // If sign in fails, display a message to the user.
                        Toast.makeText(MainActivity.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                        //updateUI(null);
                    }

                }
            });
}
0
try this 

// Facebook Button
LoginButton loginButton = findViewById(R.id.loginbtn);
loginButton.setVisibility(View.GONE)



// Your Custom Button

 binding.fbBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                loginButton.callOnClick();
            }
        });

Not the answer you're looking for? Browse other questions tagged or ask your own question.