Combining Facebook and Google auth for Firebase Android

痞子三分冷 提交于 2021-02-06 12:52:36

问题


Background

Hello, I'm new with Firebase for Android and I'm trying to implement the Facebook and Google auth/login for the first time. I followed these two tutorials for the corresponding authentication:

  • http:// firebase.google.com/docs/auth/android/google-signin
  • http:// firebase.google.com/docs/auth/android/facebook-login

Separately, the FacebookSignInActivity and GoogleSignInActivity are working as they should.

Problem

The problem is that I'm trying to use the Google and Facebook auth in the same activity, but it won't work. Like so:

result layout image

What I did

I tried to keep the FacebookSignInActivity separate from the GoogleSignInActivity by letting them extend a MainActivity and set the layout in there.

But I think I'm supposed to merge the two into one. So I tried that but I'm getting a weird nullpointer exception:

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.firebase.auth.FirebaseAuth.addAuthStateListener(com.google.firebase.auth.FirebaseAuth$AuthStateListener)' on a null object reference

I don't know why the object is null in the onCreate because I've copied the same code from the other two activities which are working:

 mAuth = FirebaseAuth.getInstance();

 mAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();
                if (user != null) {
                    // User is signed in
                    Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
                } else {
                    // User is signed out
                    Log.d(TAG, "onAuthStateChanged:signed_out");
                }
                // [START_EXCLUDE]
                updateUI(user);
                // [END_EXCLUDE]
            }
        };

I'm not even sure if I'm even supposed to merge the two into one activity. I've also checked these links:

  • https://firebase.google.com/docs/auth/android/account-linking
  • How to Link Multiple Auth Providers to an Firebase Account?

But it looks like that is something else from what I'm trying to do. If someone could help point me in the right direction, it would be gladly appreciated.


回答1:


You can try this code:

public class LoginActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener,
        View.OnClickListener {

    private static final String TAG = "SignInActivity";
    private static final int RC_SIGN_IN = 9001;

    private GoogleApiClient mGoogleApiClient;
    private FirebaseAuth mAuth;
    private FirebaseAuth.AuthStateListener mAuthListener;

    private CallbackManager mCallbackManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_login);

        // Facebook Login
        FacebookSdk.sdkInitialize(getApplicationContext());
        mCallbackManager = CallbackManager.Factory.create();

        LoginButton mFacebookSignInButton = (LoginButton) findViewById(R.id.facebook_button);
        mFacebookSignInButton.setReadPermissions("email", "public_profile", "user_birthday", "user_friends");

        mFacebookSignInButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                Log.d(TAG, "facebook:onSuccess:" + loginResult);
                firebaseAuthWithFacebook(loginResult.getAccessToken());
            }

            @Override
            public void onCancel() {
                Log.d(TAG, "facebook:onCancel");
            }

            @Override
            public void onError(FacebookException error) {
                Log.d(TAG, "facebook:onError", error);
            }
        });

        // Google Sign-In
        // Assign fields
        Button mGoogleSignInButton = (Button) findViewById(R.id.google_button);

        // Set click listeners
        mGoogleSignInButton.setOnClickListener(this);

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(getString(R.string.default_web_client_id))
                .requestEmail()
                .build();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();

        // Initialize FirebaseAuth
        mAuth = FirebaseAuth.getInstance();

        mAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
                FirebaseUser user = firebaseAuth.getCurrentUser();
                if (user != null) {
                    // User is signed in
                    Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
                } else {
                    // User is signed out
                    Log.d(TAG, "onAuthStateChanged:signed_out");
                }
            }
        };
    }

    @Override
    public void onStart() {
        super.onStart();
        mAuth.addAuthStateListener(mAuthListener);
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mAuthListener != null) {
            mAuth.removeAuthStateListener(mAuthListener);
        }
    }

    private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
        Log.d(TAG, "firebaseAuthWithGooogle:" + acct.getId());
        AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());

                        // If sign in fails, display a message to the user. If sign in succeeds
                        // the auth state listener will be notified and logic to handle the
                        // signed in user can be handled in the listener.
                        if (!task.isSuccessful()) {
                            Log.w(TAG, "signInWithCredential", task.getException());
                            Toast.makeText(LoginActivity.this, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                        } else {
                            startActivity(new Intent(LoginActivity.this, MainActivity.class));
                            finish();
                        }
                    }
                });
    }

    private void firebaseAuthWithFacebook(AccessToken token) {
        Log.d(TAG, "handleFacebookAccessToken:" + token);

        final AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());

                        // If sign in fails, display a message to the user. If sign in succeeds
                        // the auth state listener will be notified and logic to handle the
                        // signed in user can be handled in the listener.
                        if (!task.isSuccessful()) {
                            Log.w(TAG, "signInWithCredential", task.getException());
                            Toast.makeText(LoginActivity.this, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                        } else {
                            startActivity(new Intent(LoginActivity.this, MainActivity.class));
                            finish();
                        }
                    }
                });
    }

 @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.google_button:
                signIn();
                break;
            default:
                return;
        }
    }

    private void signIn() {
        Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }
  @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        mCallbackManager.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                // Google Sign In was successful, authenticate with Firebase
                GoogleSignInAccount account = result.getSignInAccount();
                firebaseAuthWithGoogle(account);
            } else {
                // Google Sign In failed
                Log.e(TAG, "Google Sign In failed.");
            }
        }
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        // An unresolvable error has occurred and Google APIs (including Sign-In) will not
        // be available.
        Log.d(TAG, "onConnectionFailed:" + connectionResult);
        Toast.makeText(this, "Google Play Services error.", Toast.LENGTH_SHORT).show();
    }

}

Please let me know if you have any questions.




回答2:


Maybe anyone still looking for solution:

In Activity( yourLoginActivity.class)

*Create a constant int to represents the requestCode for ActivityForResult

   // You can change to any Value just be unique
   private static final int RC_SIGN_IN = 1001; 

–> declare GoogleApiClient, FirebaseAuth, AuthStateListener and the CallbackManager

private static final String TAG = "LoginActivity";
private static final int RC_SIGN_IN = 1001;
private GoogleApiClient mGoogleApiClient;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private CallbackManager mCallbackManager;

–> Initialize the variables declared above:

 mCallbackManager = CallbackManager.Factory.create();  mAuth = FirebaseAuth.getInstance();  mAuthListener = new FirebaseAuth.AuthStateListener() {
     @Override
     public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
         FirebaseUser user = firebaseAuth.getCurrentUser();
         if (user != null) {
             // User is signed in
             Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
         } else {
             // User is signed out
             Log.d(TAG, "onAuthStateChanged:signed_out");
         }
     }  };

–> Get reference to SingInButton and LoginButton:

  LoginButton facebookLoginButton = findViewById(R.id.login_facebook_button);
  SignInButton mGoogleSignInButton = findViewById(R.id.sign_in_button);

–> Handle the SingInButton and LoginButton:

 facebookLoginButton.setReadPermissions("email", "public_profile", "user_birthday");
 facebookLoginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
     @Override
     public void onSuccess(LoginResult loginResult) {
         firebaseAuthWithFacebook(loginResult.getAccessToken());
     }

     @Override
     public void onCancel() {
         Toast.makeText(LoginActivity.this, "Succes", Toast.LENGTH_SHORT).show();
     }

     @Override
     public void onError(FacebookException error) {
         Toast.makeText(LoginActivity.this, "Succes", Toast.LENGTH_SHORT).show();
     }
 });

 mGoogleSignInButton.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {
         signIn();
     }
 });

–> Manage the GoogleSingInOptions and GoogleApiClient

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(getString(R.string.default_web_client_id))
        .requestEmail()
        .build();

mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
        .build();

–> Handle the Facebook Login

   private void authWithFacebook(AccessToken token) {
   Log.d(TAG, "handleFacebookAccessToken:" + token);
   final AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
    if (mAuth.getCurrentUser() != null) {
        mAuth.getCurrentUser().linkWithCredential(credential)
                .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                Toast.makeText(LoginActivity.this, "Logged IN", Toast.LENGTH_LONG).show();
            }
        })

                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        e.printStackTrace();
                        Log.e(TAG, "onFailure: " + e.getMessage());
                        mAuth.signInWithCredential(credential).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                Toast.makeText(LoginActivity.this, "Logged IN", Toast.LENGTH_LONG).show();
                            }
                        });
                    }
                });
    } else {
        mAuth.signInWithCredential(credential);
    }
}

–> Handle the Google Login:

  pprivate void authWithGoogle(final GoogleSignInAccount acct) {
    Log.d(TAG, "firebaseAuthWithGooogle:" + acct.getId());
    final AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
    if (mAuth.getCurrentUser() != null) {
        mAuth.getCurrentUser().linkWithCredential(credential).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
            @Override
            public void onSuccess(AuthResult authResult) {
                Toast.makeText(LoginActivity.this, "Logged IN", Toast.LENGTH_LONG).show();
            }
        })

                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        e.printStackTrace();
                        Log.e(TAG, "onFailure: " + e.getMessage());
                        mAuth.signInWithCredential(credential).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
                            @Override
                            public void onSuccess(AuthResult authResult) {
                                Toast.makeText(LoginActivity.this, "Logged IN", Toast.LENGTH_LONG).show();
                            }
                        });
                    }
                });
    }else{
        mAuth.signInWithCredential(credential);
    }
}

–> Override the onConnectionFailed():

 @Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    // An unresolvable error has occurred and Google APIs (including Sign-In) will not
    // be available.
    Log.d(TAG, "onConnectionFailed:" + connectionResult);
    Toast.makeText(this, "Google Play Services error.", Toast.LENGTH_SHORT).show();
}

–> Singing in and calling the onActivityForResult()

 private void signIn() {
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
}

–> Implement GoogleApiClient.OnConnectionFailedListener

LoginActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener{
....
 }

Be sure you have ENABLED FACEBOOK SDK Login FROM FIREBASE CONSOLE AND SET UP CORRECTLY!




回答3:


Somebody wanting to do this in Kotlin in a Fragment

class LoginFragment(): Fragment() ,  GoogleApiClient.OnConnectionFailedListener {

    override fun onConnectionFailed(p0: ConnectionResult) {
        Toast.makeText(activity, "Google Play Services error.", Toast.LENGTH_SHORT).show();
    }

    private val TAG = "SignInActivity"
    private val RC_SIGN_IN = 9001
    private var mGoogleApiClient: GoogleApiClient? = null
    private var mAuth: FirebaseAuth? = null
    private var mAuthListener: FirebaseAuth.AuthStateListener? = null
    private var mCallbackManager: CallbackManager? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.likes_fragment, container, false)
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        FacebookSdk.sdkInitialize(activity);
        mCallbackManager = CallbackManager.Factory.create()

        google_container.setOnClickListener {
            signIn()
        }

        // Facebook Button (LoginButton) from xml
        login_button.setReadPermissions("email", "public_profile")
        login_button.fragment = this
        login_button.run {
            registerCallback(mCallbackManager, object:  FacebookCallback<LoginResult> {
                override fun onSuccess(result: LoginResult?) {
                    Log.e(TAG, "Succesfull Facebook Sign In")
                    firebaseAuthWithFacebook(result?.accessToken!!)
                }

                override fun onCancel() {
                    Log.e(TAG, "Cancelled Facebook Sign In")
                }

                override fun onError(error: FacebookException?) {
                    Log.e(TAG, "Facebook sign in error : " + error.toString())
                }

            })
        }

        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .build()
        mGoogleApiClient = GoogleApiClient.Builder(activity!!.applicationContext)
            .enableAutoManage(this.activity!! /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build()

        mAuth = FirebaseAuth.getInstance()
        mAuthListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
            val user = firebaseAuth.currentUser
            if (user != null) {
                // User is signed in
                Log.e(TAG, "onAuthStateChanged:signed_in:" + user.uid)
            } else {
                // User is signed out
                Log.e(TAG, "onAuthStateChanged:signed_out")
            }
        }
    }


    fun signIn() {
        val signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient)
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        mCallbackManager!!.onActivityResult(requestCode, resultCode, data);

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            val result = Auth.GoogleSignInApi.getSignInResultFromIntent(data)
            if (result.isSuccess) {
                // Google Sign In was successful, authenticate with Firebase
                val account = result.signInAccount
                firebaseAuthWithGoogle(account!!)
            } else {
                // Google Sign In failed
                Log.e(TAG, "Google Sign In failed.");
            }
        }
    }

    private fun firebaseAuthWithGoogle(token : GoogleSignInAccount) {
        Log.e(TAG, "handleGoogleAccessToken:" + token);
        val credential = GoogleAuthProvider.getCredential(token.idToken,null)
        mAuth!!.signInWithCredential(credential)
            .addOnCompleteListener(activity as MainActivity, object : OnCompleteListener<AuthResult> {
                override fun onComplete(task: Task<AuthResult>) {
                    Log.e(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
                    if(!task.isSuccessful){
                        Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
                    }else{
                        Toast.makeText(activity, "Success", Toast.LENGTH_SHORT).show();
                    }
                }

            })

    }


     private fun firebaseAuthWithFacebook(token : AccessToken) {
         Log.e(TAG, "handleFacebookAccessToken:" + token);
         val credential = FacebookAuthProvider.getCredential(token.token)
         mAuth!!.signInWithCredential(credential)
             .addOnCompleteListener(activity as MainActivity, object : OnCompleteListener<AuthResult> {
                 override fun onComplete(task: Task<AuthResult>) {
                     Log.e(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
                     if(!task.isSuccessful){
                         Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();

                     }else{
                         Toast.makeText(activity, "Success", Toast.LENGTH_SHORT).show();

                     }
                 }

             })

    }
}


来源:https://stackoverflow.com/questions/39778301/combining-facebook-and-google-auth-for-firebase-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!