简体   繁体   English

Facebook使用Firebase BaaS登录Android

[英]Facebook login with Android using Firebase BaaS

I'm following this Firebase tutorial to integrate Facebook to my app. 我正在按照 Firebase教程将Facebook集成到我的应用程序中。 Everything looks good, except by the fact that I'm having this exception: 一切都很好看,除了我有这个例外的事实:

com.google.firebase.auth.FirebaseAuthUserCollisionException: An account already exists with the same email address but different sign-in credentials. com.google.firebase.auth.FirebaseAuthUserCollisionException:已存在具有相同电子邮件地址但登录凭据不同的帐户。 Sign in using a provider associated with this email address. 使用与此电子邮件地址关联的提供商登录。

Fair enought, considering that this is exactly what I'm trying to do. 公平对待,考虑到这正是我正在努力做的事情。 First I created a code to integrate gmail to my app, and logged in using my email account. 首先,我创建了一个代码,将gmail集成到我的应用程序,并使用我的电子邮件帐户登录。 Then I tried to log-in with Facebook, and got the error. 然后我尝试使用Facebook登录,并得到了错误。

Searching how to work this out, I found here that 搜索如何解决这个问题,我在这里找到了

FirebaseAuthUserCollisionException thrown if there already exists an account with the email address asserted by the credential. 如果已存在具有凭证声明的电子邮件地址的帐户,则抛出FirebaseAuthUserCollisionException。 Resolve this case by calling fetchProvidersForEmail(String) and then asking the user to sign in using one of them. 通过调用fetchProvidersForEmail(String)解决此问题,然后要求用户使用其中一个登录。

Finally the problem is that I'm not sure I'm using correctly the fetchProvidersForEmail method, because my task is not being successful (check the last block of code). 最后问题是我不确定我是否正确使用了fetchProvidersForEmail方法,因为我的任务没有成功(检查最后一段代码)。

Can anyone give a support? 任何人都可以给予支持吗? Thank you, 谢谢,

*The code below is currently supporting login for gmail and Facebook. *以下代码目前支持登录gmail和Facebook。 The method which I'm speaking here is the last one, handleFacebookAccessToken . 我在这里讲的方法是最后一个, handleFacebookAccessToken

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

/**
 * References
 * https://developers.google.com/identity/sign-in/android/sign-in#configure_google_sign-in_and_the_googleapiclient_object
 */

// Here a simple Sign-In button is used to initiate authentication. In this step you will
// implement the logic to Sign-In with Google then use that Google account to authenticate with
// Firebase.

private static final String TAG = "SignInActivity";
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private FirebaseAuth mAuth;

private FirebaseAuth.AuthStateListener mAuthListener;

LoginButton facebookLogin;
CallbackManager cM;

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

    FacebookSdk.sdkInitialize(this.getApplicationContext());
    setContentView(R.layout.activity_sign_in);

    cM = CallbackManager.Factory.create();
    facebookLogin = (LoginButton) findViewById(R.id.sign_in_button_facebook);
    if (facebookLogin != null) {
        facebookLogin.setReadPermissions("public_profile", "email", "user_friends");
        facebookLogin.registerCallback(cM, new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                Log.d(TAG, "facebook:onSuccess:" + loginResult);
                handleFacebookAccessToken(loginResult.getAccessToken());
            }

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

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

    // Configure Google Sign-In to request the user data required by the app. For example, to
    // configure Google Sign-In to request users' ID and basic profile information, create a
    // GoogleSignInOptions object with the DEFAULT_SIGN_IN parameter (ID and basic profile are
    // included in DEFAULT_SIGN_IN). To request users' email addresses as well, create the
    // GoogleSignInOptions object with the requestEmail option.
    GoogleSignInOptions mGoogleSignInOptions = new GoogleSignInOptions
            .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .build();

    // Create a GoogleApiClient object with access to the Google Sign-In API and the options
    // specified. Note: To use enableAutoManage, your activity must extend FragmentActivity or
    // AppCompatActivity (a subclass of FragmentActivity), both of which are part of the Android
    // Support Library. You can use GoogleApiClient in a Fragment; however, the fragment's
    // parent activity must be a FragmentActivity. If you can't extend FragmentActivity, you
    // must manually manage the GoogleApiClient connection lifecycle.
    mGoogleApiClient = new GoogleApiClient
            .Builder(this)
            .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
            .addApi(Auth.GOOGLE_SIGN_IN_API, mGoogleSignInOptions)
            .build();

    // Configure the sign in button.
    SignInButton mSignInButton = (SignInButton) findViewById(R.id.sign_in_button);
    if (mSignInButton != null) {
        mSignInButton.setSize(SignInButton.SIZE_STANDARD);
        mSignInButton.setOnClickListener(this);
    }

    // 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 onClick(View v) {
    switch (v.getId()) {
        case R.id.sign_in_button:
            signIn();
            break;
    }
}

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

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

// Handle sign-in button taps by creating a sign-in intent with the getSignInIntent method, and
// starting the intent with startActivityForResult. Starting the intent prompts the user to
// select a Google account to sign in with. If you requested scopes beyond profile, email, and
// openid, the user is also prompted to grant access to the requested resources.
private void signIn() {
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
}

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

// Handle the result of the Google Sign In in the activity's onActivityResult method, which
// retrieve the sign-in result with getSignInResultFromIntent.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    cM.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        handleSignInResult(result);
    }
}

// After you retrieve the sign-in result, you can check if sign-in succeeded with the isSuccess
// method. If sign-in succeeded, you can call the getSignInAccount method to get a
// GoogleSignInAccount object that contains information about the signed-in user, such as the
// user's name. You can also get the user's email address with getEmail, the user's Google ID
// (for client-side use) with getId, and an ID token for the user with with getIdToken. If you
// need to pass the currently signed-in user to a backend server, send the ID token to your
// backend server and validate the token on the server.
public void handleSignInResult(GoogleSignInResult result) {
    if (result.isSuccess()) {
        GoogleSignInAccount account = result.getSignInAccount();

        // Google Sign In was successful, authenticate with Firebase.
        firebaseAuthWithGoogle(account);

    } else {
        // Google Sign In failed
        // TODO: 26/06/2016 Handle no internet connection
        Log.e(TAG, "Google Sign In failed.");
    }
}

// Add the required firebaseAuthWithGoogle method to authenticate with the signed in Google
// account.
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(SignInActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show();

                    } else {
                        startActivity(new Intent(SignInActivity.this, MainActivity.class));
                        finish();
                    }
                }
            });
}

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

    // This commented block below is what is on the tutorial, but gives the exceptio explained.
    /*
    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(SignInActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show();
            }

            // ...
        }
    });
    */

    mAuth.fetchProvidersForEmail("i_put_here_my_email@gmail.com").addOnCompleteListener(this, new OnCompleteListener<ProviderQueryResult>() {
        @Override
        public void onComplete(@NonNull Task<ProviderQueryResult> 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(SignInActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show();
            } else {
                startActivity(new Intent(SignInActivity.this, MainActivity.class));
                finish();
            }
        }
    });
}

} }

AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
        mFirebaseAuth.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(SignInActivity.this, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();

                            //((FirebaseAuthException)task.getException()).getErrorCode();

                        }

                    }

                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        if(e instanceof  FirebaseAuthUserCollisionException)
                        {
                            //Handle Auth Error Here
                            Toast.makeText(SignInActivity.this, e.toString(),
                                    Toast.LENGTH_SHORT).show();

                        }else if(e instanceof FirebaseAuthInvalidUserException)
                        {
                            //Handle Auth Error Here
                            Toast.makeText(SignInActivity.this, e.toString(),
                                    Toast.LENGTH_SHORT).show();

                        }
                    }
        });

Note: If we are able to get a Error Code for those Auth exceptions then that is better than using type check(instanceOf) 注意:如果我们能够获得那些Auth异常的错误代码,那么这比使用类型检查更好(instanceOf)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android应用程序-使用Facebook登录与Firebase身份验证 - Android app - using facebook login with firebase auth 在android中使用firebase登录facebook时出现InflateException - InflateException while login with facebook using firebase in android Firebase Facebook 登录 android - Firebase Facebook login android 在Android应用中使用Firebase(BaaS)存储电子邮件和密码时,如何包含用户名? - How do you include a username when storing email and password using Firebase (BaaS) in an Android app? 如何在Android Studio中使用带有片段和Viewpager的Facebook登录进行Firebase身份验证? - How to Firebase Authenticate Using Facebook Login in Android Studio with fragments and viewpager? 使用Facebook Android登录 - Login using facebook android 在Android中使用Facebook登录 - using facebook login in android 在带有firebase作为baas服务的android中,如何仅检索特定的子节点 - in android with firebase as baas service,how to retrive only specific child nodes Android Firebase:无需使用Google,facebook等登录提供程序即可检索单个用户数据和自定义登录 - Android Firebase:To retrieve single user data and custom login without using login providers like google,facebook etc Android中的Firebase Facebook和Google登录错误 - Firebase facebook and google login error in android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM