Custom Facebook Login Button - Android

AndroidFacebookFacebook Sdk-4.0

Android Problem Overview


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?

Thanks in advance!

Android Solutions


Solution 1 - Android

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
}

Solution 2 - Android

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);
     }
    

Solution 3 - Android

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

Solution 4 - Android

(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.

Solution 5 - Android

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

Solution 6 - Android

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();
                        }

                    }
                });
    } 
 }

Solution 7 - Android

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);
                    }

                }
            });
}

Solution 8 - Android

try this 

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


// Your Custom Button

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNeoVeView Question on Stackoverflow
Solution 1 - AndroidHarvi SirjaView Answer on Stackoverflow
Solution 2 - AndroidShehabicView Answer on Stackoverflow
Solution 3 - AndroidHarpreet SinghView Answer on Stackoverflow
Solution 4 - AndroidWeselyView Answer on Stackoverflow
Solution 5 - AndroidBiskrem MuhammadView Answer on Stackoverflow
Solution 6 - AndroidEmon Hossain MunnaView Answer on Stackoverflow
Solution 7 - AndroidThiago SilvaView Answer on Stackoverflow
Solution 8 - Androiduser9883843View Answer on Stackoverflow