当前位置: 首页 > 知识库问答 >
问题:

使用Facebook登录集成的Firebase身份验证用户的空电子邮件字段(Firebase 3.0)

孙子民
2023-03-14

我已经成功地从https://Firebase.google.com/docs/Auth/android/facebook-login部署了用于将Firebase身份验证登录与Facebook集成的教程代码。在Firebase身份验证控制台中成功创建了用户

但是,我注意到user对象中的Email字段为空(-)。奇怪的是,我成功地使用获取的令牌使用GraphRequest直接从provider结果对象检索电子邮件信息。

根据我阅读的文档(https://firebase.google.com/docs/reference/android/com/google/firebase/auth/firebaseuser.html#getemail()),电子邮件字段应该从登录提供程序填充。

另外一些奇怪的行为:

  1. 成功登录后,onAuthStateChanged会被调用两次。firebaseauth.getCurrentUser().getProviderId()的值在两种情况下都是Firebase
  2. 我尝试从FirebaseUser对象user.getProviderData()中列出提供者。我有两个提供商:firebase和Facebook.com
  3. 当我尝试使用FirebaseUser.UpdateEmail(event.getEmail())更新电子邮件时,我得到了以下错误:发生了内部错误。[EMAIL_EXISTS]

是我错过了什么还是我做错了什么?

这是我的代码:

public class LoginActivity extends AppCompatActivity {
    private static final String TAG = "LOGIN_ACTIVITY";
    private static final int RC_SIGN_IN = 777;
    private EventBus eventBus;
    private SweetAlertDialog pDialog;

    private FirebaseAuth mAuth;
    private FirebaseAuth.AuthStateListener mAuthListener;
    private CallbackManager mCallbackManager;
    private ImageView mPasswordVisibilityView;
    private TextView txtPassword;
    private boolean justEnteredAuthStateChanged = false;
    private GoogleApiClient mGoogleApiClient;


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

        setContentView(R.layout.login);

        // Firebase
        mAuth = FirebaseAuth.getInstance();

        mAuthListener = new FirebaseAuth.AuthStateListener() {
            @Override
            public void onAuthStateChanged(@NonNull final FirebaseAuth firebaseAuth) {
                final FirebaseUser user = firebaseAuth.getCurrentUser();
                if (user != null) {
                    // User is signed in
                    Util.logassert("Auth Provider = " + firebaseAuth.getCurrentUser().getProviderId()); // this is called twice, values of Provider = Firebase 
                    Util.logassert("total provider = " + user.getProviderData().size()); // output = 2. "Firebase" and "facebook.com"
                    for (int i = 0; i < user.getProviderData().size(); i++) {
                        UserInfo info = user.getProviderData().get(i);
                        Util.logassert(info.getProviderId() + ", email = " + info.getEmail()); // both empty
                        Util.logassert("current provider = " + info.getProviderId() + " - " + info);
                    }

                } else {
                    Util.logassert("onAuthStateChanged user logged out");
                }
                // ...

            }
        };
        mAuth.addAuthStateListener(mAuthListener);

        // Firebase Facebook TapAuth
        // Initialize Facebook Login button

        mCallbackManager = CallbackManager.Factory.create();

        LoginManager.getInstance().registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                Util.logassert("facebook:onSuccess:" + loginResult);
                handleFacebookAccessToken(loginResult.getAccessToken());
                Util.logassert("granted = " + loginResult.getRecentlyGrantedPermissions()); // output [email and public_profile]
                Util.logassert("denied = " + loginResult.getRecentlyDeniedPermissions());
            }

            @Override
            public void onCancel() {
                Util.logassert("facebook:onCancel");
                // ...
            }

            @Override
            public void onError(FacebookException error) {
                Util.logassert("facebook:onError" + error.getMessage());
                // ...
            }
        });

        FancyButton btnFacebook = (FancyButton) findViewById(R.id.btn_facebook_share);
        btnFacebook.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LoginManager.getInstance().logInWithReadPermissions(LoginActivity.this, Arrays.asList("public_profile", "email"));
                Util.logassert("try facebook login");
            }
        });



        txtPassword = (EditText) findViewById(R.id.input_password);
    }



    private void handleFacebookAccessToken(AccessToken token) {
        Util.logassert("handleFacebookAccessToken:" + token);

        GraphRequest request = GraphRequest.newMeRequest(
                token,
                new GraphRequest.GraphJSONObjectCallback() {
                    @Override
                    public void onCompleted(
                            JSONObject object,
                            GraphResponse response) {
                        // Application code
                        Log.v("LoginActivity", response.toString());
                        Util.logassert("graph res = " + response.getRawResponse());

                        try {
                            /* successfully output email address from graph request here */
                            FbGraphEvent event = new FbGraphEvent(response.getJSONObject().getString("email"), response.getJSONObject().getString("name"));
                            EventBus.getDefault().postSticky(event);
                        } catch (Exception e) {
                            Log.e("MomInvoice", "Error in parsing json fb graph", e);
                        }
                    }
                });
        Bundle parameters = new Bundle();
        parameters.putString("fields", "email,name");
        request.setParameters(parameters);
        request.executeAsync();

        AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());

        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Util.logassert("signInWithCredential:onComplete:" + task.isSuccessful());


                        if (!task.isSuccessful()) {
                            Util.logassert("signInWithCredential failed coz = " + task.getException().getMessage());
                            Toast.makeText(LoginActivity.this, "Authentication failed :(",
                                    Toast.LENGTH_SHORT).show();
                        }

                    }
                });
    }


    @Override
    public void onStart() {
        super.onStart();
        Util.logassert("masuk onStart LoginActivity");
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

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

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);

        if (mCallbackManager != null) {
            mCallbackManager.onActivityResult(requestCode, resultCode, data);
            Util.logassert("hasilx " + requestCode + " = " + resultCode);
        }

    }
}

共有2个答案

梁华皓
2023-03-14

有些Facebook账户是使用手机号码创建的,所以每当我们请求电子邮件地址时,我们得到的是一个空字符串

在下面的图像中,您可以看到facebook帐户可以将他们的主要联系人设置为电子邮件地址或移动号码。因此,如果一个人将手机号码标记为主要号码,那么他们的电子邮件地址将无法检索。

在我的例子中,我忘记了验证我的facebook账户,所以最初我的电子邮件地址甚至没有显示在主要联系人中。所以,如果您没有获得电子邮件地址,那么请转到常规设置,看看主帐户是否设置为电子邮件地址。

闻人花蜂
2023-03-14

在阅读了firebase-talk google group中的帖子后,我找到了答案,这里有https://groups.google.com/forum/#!topic/firebase-talk/gpgnq-iktlo。发生这个问题是因为我在Firebase身份验证登录方法中使用了“允许使用相同的电子邮件地址创建多个帐户”。

所以我把这个选项改成:“防止用相同的电子邮件地址创建多个帐户”,这样就可以正常工作了。就这么简单。这是真的,我需要更多的逻辑合并帐户有相同的电子邮件地址,但这是好的。

也许其他有同样问题的人也可以尝试一下,希望它也能得到解决。

 类似资料:
  • 我可以在用户注册后发送一封验证邮件,但是用户会自动登录。在用户验证其电子邮件之前,我如何阻止他们登录?

  • 如何使用firebase中的验证电子邮件验证使用电子邮件和密码登录的用户?这背后的逻辑是如何工作的,它在代码中会是什么样子? 解决方案/帮助:对于那些仍在寻找答案的人,我找到了这篇文章 堆栈溢出 帖子

  • 该应用程序应该接受用户电子邮件和密码,并使用Firebase身份验证作为后端。我使用像素2作为模拟器。每次应用程序处理登录功能时,它都会崩溃。 下面是Java文件和gradle文件 Java文件:

  • 我目前已经设置了下面的Auth组件,它工作得很好,但是我的客户现在希望能够为用户提供使用用户名或电子邮件地址登录的选项。 我当前的设置: 我如何才能更改此项,以便日志需要“电子邮件”或新字段“用户名”。 我会假设一个OR语句,但是下面的不工作:

  • 我也不会得到一个错误,如果我登录我的电子邮件和密码没有验证电子邮件。 非常感谢你事先的帮助。

  • 我使用Firebase身份验证和电子邮件验证来实现用户注册,如下所示: 用户注册完成后,我可以在Firebase控制台内的Authentication菜单上看到电子邮件。然后我点击了电子邮件上的验证链接,在浏览器上得到了这样的消息: 返回false。所以电子邮件验证过程没有成功完成。这里怎么了? 我使用的是CompilesDKVersion29和Firebase-Auth19.3.2。