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

Ibr*_*lem 2 android firebase firebase-authentication firebase-realtime-database

在此输入图像描述

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

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



        }
    });
Run Code Online (Sandbox Code Playgroud)

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

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

}
Run Code Online (Sandbox Code Playgroud)

这是我登录的方式:

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

                }
            });
        }
    });
Run Code Online (Sandbox Code Playgroud)

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

如何使userIdAuth中的密钥等于userId数据库中的内容以及如何使用该功能?

Kev*_*eil 6

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


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

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

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

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

更新数据库结构

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

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

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

boolean mIsNewUser = false; 
Run Code Online (Sandbox Code Playgroud)

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

每当您成功创建用户时,他们也会自动登录.所以,如果你移动你的呼叫generateUser()createUserWithEmailAndPassword OnCompleteListener你的AuthStateListener,你可以访问所创建的用户uid.签署现有用户时,也将数据库查询移动到AuthStateListener同一位置,这样我们就可以访问用户了uid.我还要为数据库查询创建一个辅助方法来调用getExistingUserInfo.作为一个FYI,用于创建和签名用户的onComplete()回调OnCompleteListeners使您可以访问AuthResult根据API有一个返回当前用户的方法,但文档说要访问用户信息AuthStateListener.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新generateUser()帮助器方法以使用uid而不是推送ID:

我将假设您希望保留现有的数据库结构,并按照建议为所有用户添加单个位置.基于此,我对您使用的写入操作进行了一些更改generateUser().主要是,而不是使用setValue()写入我正在使用的数据库updateChildren().通过使用,updateChildren()我们可以利用Firebase进行原子更新的能力.这将允许我们写入相应的学生组位置和同时存储所有用户的位置.通过采用这种方法,如果对任一位置的写入操作失败,则不会更新位置.这样,您可以确定如果将学生添加到组中,他们也将列在allUsers位置.

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);
    }    
    }
Run Code Online (Sandbox Code Playgroud)

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

如上所述,通过为所有用户创建单个位置,您可以降低用户在登录时查找用户信息的查询的复杂性.同样,如果您需要按组存储用户,您可以保留该信息,但请务必保留如果用户信息更改,则更新两个位置.

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) {

                            }
                        });

}
Run Code Online (Sandbox Code Playgroud)

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

FirebaseAuth.getInstance().createUserWithEmailAndPassword(mUser.getEmail(), mUser.getPassword()).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(Task<AuthResult> task) {

                    if (task.isSuccessful()) {

                        //set boolean used in the AuthListener
                        mIsNewUser = true;
                        Toast.makeText(getActivity(), "Sucsses", Toast.LENGTH_SHORT).show();

                    } else {
                        Toast.makeText(getActivity(), "not Sucsses", Toast.LENGTH_SHORT).show();
                    }
                }
            });
Run Code Online (Sandbox Code Playgroud)