如何知道哪个用户尝试登录?

时间:2016-09-11 18:45:23

标签: android firebase firebase-realtime-database firebase-authentication

enter image description here

使用电子邮件和密码创建用户。这就是我注册的方式:

    mSignup.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            mEmailStr = removeSpaces(mEmail.getText().toString());
            mPasswordStr = mPassword.getText().toString();
            mUsernameStr = mUsername.getText().toString();
            mIsSgl = mSglCheckBox.isChecked();
            mUsernameStr=mUsername.getText().toString();
            final User mUser = new User();
            mUser.setEmail(mEmailStr);
            mUser.setPassword(mPasswordStr);
            mUser.setIsSgl(mIsSgl);
            mUser.setStudyGroupName(mStudyGroupName);
            mUser.setUsername(mUsernameStr);
            FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(Task<AuthResult> task) {


                    if (task.isSuccessful()) {
                        Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();
                        generateUser(mUser);
                        startActivity(new Intent(getActivity(), MainActivity.class));
                    } else {
                        Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
                    }
                }
            });



        }
    });

这就是我将数据推送到数据库的方式:

 public void generateUser(User user)
  {

    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference users;
    if(user.getIsSgl())
    {
        users = database.getReference(user.getStudyGroupName()).child("SGL");
    }
    else
    {
        users = database.getReference(user.getStudyGroupName()).child("Student");
    }

    users.push().setValue(user);

}

这是我登录的方式:

mSignin.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            mEmailStr = SignupActivityFragment.removeSpaces(mEmail.getText().toString());
            mPasswordStr = mPassword.getText().toString();

            mAuth.signInWithEmailAndPassword(mEmailStr, mPasswordStr).addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(Task<AuthResult> task) {
                    if (task.isSuccessful()){


                        FirebaseDatabase database = FirebaseDatabase.getInstance();                            
                        // thats not worked for me
                        database.getReference("StudyGroups").child("Student").orderByChild("email").equalTo(mEmailStr).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                for (DataSnapshot childSnapShot : dataSnapshot.getChildren()) {
                                    userKey = childSnapShot.getKey();
                                }

                                Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
                                Log.v("himaAbousalem",userKey);
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {

                            }
                        });
                        Toast.makeText(getActivity(), "Sucsses ", Toast.LENGTH_SHORT).show();
                        startActivity (new Intent(getActivity(),Controller.class));
                    }else {
                        Toast.makeText(getActivity(), "not sucsses", Toast.LENGTH_SHORT).show();
                    }

                }
            });
        }
    });

我想查询数据库,以便当用户通过电子邮件和密码登录时,它会从数据库中返回该用户的所有数据。

如何让Auth中userId的密钥等于数据库中的userId,如何使用该功能?

1 个答案:

答案 0 :(得分:6)

tl; dr - 在这种情况下,使用Fireabase Auth生成的关联uid存储每个用户,而不是使用推送ID。

在您的情况下,使用推送ID存储特定于每个用户的信息的挑战是,当用户登录时,您不知道您在第一次存储其信息时使用的推送ID。要在每次登录时查找用户,您必须搜索数据库中的每个用户,直到找到匹配的电子邮件/密码以检索其正确的个人资料信息 - 您拥有的用户越多,搜索所需的时间就越长。另一种可能更快的替代方法是使用Firebase身份验证来创建用户,使用Firebase数据库来存储任何特定于用户的信息。

使用Firebase身份验证创建新用户时,它会为用户分配唯一的用户ID,该用户ID在用户的整个生命周期内都是相同的。然后,您可以使用Firebase Auth生成的唯一用户ID而不是推送ID将用户信息存储在数据库中。用户下次登录时,您会从Firebase Auth获取用户uid并使用它来查询数据库以获取该用户的信息。

查看指南,了解如何创建基于密码的用户以及如何使用Firebase身份验证对用户进行签名:Create a password-based account

为了使用Firebase Auth生成的唯一uid,我建议您对代码进行一些更改。

更新数据库结构

我建议您在创建/登录用户时添加新位置(可能是&#34; allUsers&#34;)来更新数据库结构。现在看起来你正在把学生分成小组。如果您需要保留此结构,出于身份验证之外的原因,您可以将其与我的建议一起使用。存储所有用户的单个位置的原因是,当用户登录时,您需要一个明确的位置来查询。使用Firebase Auth时,如果没有存储所有用户的单个位置,则无法分辨用户属于哪个组当他们第一次登录时。您必须检查每个组才能找到匹配项,这可能需要很长时间。拥有存储所有用户的位置可以解决该问题。此外,从该单个位置检索用户信息的查询要简单得多。如果您确实需要在多个位置保留用户的信息,请务必在发生任何更改时更新两个地方的信息。

创建一个类变量,用于区分创建用户和登录现有用户。

如果您使用相同的Activity创建新用户并登录现有用户,则创建一个布尔变量,以区分创建新用户的时间和现有用户的登录时间。将使用它稍后在AuthStateListener。如果您在一般登录的单独活动中处理用户创建,则您不应该需要此变量,因为每个活动都有一个单独的AuthStateListener

boolean mIsNewUser = false; 

将createUser()的调用从create user completion listener移动到AuthStateListener。还要将数据库查询从登录完成侦听器移动到AuthStateLisener

每当您成功创建用户时,他们也会自动登录。因此,如果您将来自generateUser() createUserWithEmailAndPassword的{​​{1}}移至OnCompleteListener,则可以访问已创建的用户AuthStateListener。签署现有用户时,同样将数据库查询移至uid,我们也可以访问用户AuthStateListener。我还要为名为uid的数据库查询创建一个帮助方法。作为一个FYI,getExistingUserInfo中用于创建和登录用户的onComplete()回调可让您访问OnCompleteListeners,根据API有一个返回当前用户但文档的方法说要访问AuthResult中的用户信息。

AuthStateListener

更新您的generateUser()辅助方法以使用uid而不是推送ID:

我将假设您希望保留现有的数据库结构,并按照建议为所有用户添加单个位置。基于此,我对private FirebaseAuth mAuth; private FirebaseAuth.AuthStateListener mAuthListener; @Override protected void onCreate(Bundle savedInstanceState) { 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()); if(mIsNewUser){ //call to generate user using Uid instead of pushID generateUser(mUser, user.getUid()); } else{ getExistingUserInfo(user.getUid()); } startActivity(new Intent(getActivity(), MainActivity.class)); } 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); } } 中使用的写操作进行了一些更改。主要是,而不是使用generateUser()使用setValue()写入数据库。通过使用updateChildren(),我们可以利用Firebase的原子更新功能。这将允许我们写入相应的学生组位置和同时存储所有用户的位置。通过采用这种方法,如果对任一位置的写入操作失败,则不会更新位置。这样,您可以确定如果将学生添加到组中,他们也将列在allUsers位置。

updateChildren()

更新数据库查询以使用存储所有用户的新位置

正如我上面提到的,通过为所有用户创建单个位置,您可以降低用户在登录时查找用户信息的复杂性。再次,如果您需要按组存储用户如果用户信息发生变化,请确保更新这两个位置。

private void generateUser(User user, String uid)
  {

      DatabaseReference database = FirebaseDatabase.getInstance().getReference();
    String userType;
    String allusers = "allUsers/" + uid;
    Map<String, Object> newUserUpdate = new HashMap<>();
    if (user.getUsername() != null) {
        if (user.isSgl()) {
            userType = user.getStudyGroupName() + "/" + "SGL" + "/" + uid;
        } else {
            userType = user.getStudyGroupName() + "/" + "Student" + "/" + uid;
        }

        newUserUpdate.put(userType, user.serialize());
        newUserUpdate.put(allusers, user.serialize());
        database.updateChildren(newUserUpdate);
    }    
    }

在创建用户完成侦听器中设置用于区分现有用户登录和新用户创建的变量

public void getExistingUserInfo(String uid){

 FirebaseDatabase database = FirebaseDatabase.getInstance(); 
                        database.getReference("allUsers").child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                //get user data from dataSnapshot

                                Toast.makeText(getContext(),"Userkey: " + userKey,Toast.LENGTH_LONG).show();
                                Log.v("himaAbousalem",userKey);
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {

                            }
                        });

}