![](/img/trans.png)
[英]Android Firebase, How to check if a subcollection exists within a document
[英]How to check if the particular username exists in the firebase? (Java Android)
我已经尝试了所有 StackOverflow 方法,但所有方法都在检查它是否为 null。 我想检查“用户”节点下的特定字符串。 例如:(aaaaa) (bbbbb) 或其中的子值(用户名:“aaaaa”) 如果用户在注册时输入用户名“asaaa”或“bbbbb”,将提示错误。 (我想检查 firebase 所有节点中的所有值)我在整个堆栈溢出中进行了搜索,但大多数解决方案都需要知道节点名称才能运行。 我想检索“用户”下的所有节点名称以供检查。 如果用户在注册期间使用“aaaaa”作为用户名,将在 TextInputLayout 中设置错误。
公共 class RegisterActivity 扩展 AppCompatActivity {
EditText username, fullname, email, password;
Button register;
TextView txt_login;
public String strUsername;
FirebaseAuth auth;
DatabaseReference reference;
ProgressDialog pd;
private static final String TAG = "RegisterActivity";
private static String users_from_database;
private ArrayList<String> username_list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
username = findViewById(R.id.username);
fullname = findViewById(R.id.fullname);
email = findViewById(R.id.email);
password = findViewById(R.id.password);
register = findViewById(R.id.btn_Register);
txt_login = findViewById(R.id.txt_login);
auth = FirebaseAuth.getInstance();
checkForUsername();
txt_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(RegisterActivity.this,HomeActivity.class));
}
});
register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pd = new ProgressDialog(RegisterActivity.this);
pd.setMessage("Please wait...");
pd.show();
String str_username = username.getText().toString();
String str_fullname = fullname.getText().toString();
String str_email = email.getText().toString();
String str_password = password.getText().toString();
strUsername = username.getText().toString().trim();
if (!username_list.contains(strUsername)) {
// do your job here , suppose send verification code to phone number
if(TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_fullname) || TextUtils.isEmpty(str_email) ||
TextUtils.isEmpty(str_password)){
Toast.makeText(RegisterActivity.this,"All fields are required!",Toast.LENGTH_SHORT).show();
pd.dismiss();
} else if (str_password.length() < 6) {
Toast.makeText(RegisterActivity.this,"Password must be over 6 characters.",Toast.LENGTH_SHORT).show();
pd.dismiss();
} else {
register(str_username,str_fullname,str_email,str_password);
}
} else {
username.setError("Username Exist");
}
}
});
}
private void checkForUsername(){
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users/");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot ds : snapshot.getChildren()) {
users_from_database = (String) ds.child("username").getValue();
username_list.add(users_from_database);
StringBuilder stringBuilder = new StringBuilder();
for (String s : username_list) {
stringBuilder.append(s + "\n");
}
Log.d("ZI", stringBuilder.toString());
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Log.d("ZI", "Failed");
}
});
}
private void register(final String username, final String fullname, String email, String password){
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(RegisterActivity.this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
FirebaseUser firebaseUser = auth.getCurrentUser();
String userID = firebaseUser.getUid();
firebaseUser.sendEmailVerification().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(RegisterActivity.this,"Verification Email Has Been Sent.", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d(TAG, "onFailure: Email not sent" + e.getMessage());
}
});
reference = FirebaseDatabase.getInstance().getReference().child("Users").child(username);
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("username",username.toLowerCase());
hashMap.put("fullname",fullname);
hashMap.put("email",email);
hashMap.put("password",password);
hashMap.put("imageurl","");
reference.setValue(hashMap).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if(task.isSuccessful()){
pd.dismiss();
Intent intent = new Intent(RegisterActivity.this,EmailActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
});
} else {
pd.dismiss();
Toast.makeText(RegisterActivity.this,"Register Failed",Toast.LENGTH_SHORT).show();
}
}
});
}
}
您可以创建一个公共路径usernames
,您只需在其中存储已使用且公开可见的用户名。 注册新用户时,您可以检查用户名是否已经存在。 也不要试图让所有的 then 检查是否存在一个。 只需调用路径usernames/{username}
,如果是null
则用户名不存在。 阅读所有这些内容会破坏您的 Firebase 账单。
是的,您可以按照以下步骤进行操作。
从您的DatabaseReference
获取所有username
child 并将其添加到 ArrayList。
检查用户提供的username
是否在 ArrayList(来自步骤 1 )中可用。 如果包含则设置错误,否则执行您的工作以完成注册。
更新-我认为您在执行/完成checkForUsername();
方法。 所以if...else
语句无法正常工作及其覆盖数据。 这是我的错误。 我们应该先从数据库中检查所有用户,然后再进行下一部分注册。 因此,无需在onCreate()
中单独使用checkForUsername()
方法,我们将在单击按钮时执行所有操作。 检查代码 -
register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pd = new ProgressDialog(LoginActivity.this);
pd.setMessage("Please wait...");
pd.show();
String str_username = username.getText().toString();
String str_fullname = fullname.getText().toString();
String str_email = email.getText().toString();
String str_password = password.getText().toString();
strUsername = username.getText().toString().trim();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users/");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
for (DataSnapshot ds : snapshot.getChildren()) {
users_from_database = (String) ds.child("username").getValue();
username_list.add(users_from_database);
StringBuilder stringBuilder = new StringBuilder();
for (String s : username_list) {
stringBuilder.append(s + "\n");
}
// Log.d("ZI", stringBuilder.toString());
if (!username_list.contains(strUsername)) {
// do your job here , suppose send verification code to phone number
if (TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_fullname) || TextUtils.isEmpty(str_email) ||
TextUtils.isEmpty(str_password)) {
Toast.makeText(LoginActivity.this, "All fields are required!", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else if (str_password.length() < 6) {
Toast.makeText(LoginActivity.this, "Password must be over 6 characters.", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else {
register(str_username, str_fullname, str_email, str_password);
}
} else {
username.setError("Username Exist");
pd.dismiss();
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Log.d("ZI", "Failed");
}
});
}
});
更新 - 您可以检查DataSnapshot
是否存在。 如果不存在,那么你可以设置测试值来启动你的数据库。 这只会执行一次。 你可以检查 -
register.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pd = new ProgressDialog(LoginActivity.this);
pd.setMessage("Please wait...");
pd.show();
String str_username = username.getText().toString();
String str_fullname = fullname.getText().toString();
String str_email = email.getText().toString();
String str_password = password.getText().toString();
strUsername = username.getText().toString().trim();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Users/");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (!snapshot.exists()) {
HashMap<String, Object> testHash = new HashMap<>();
testHash.put("username", "testusername");
ref.child("test")
.setValue(testHash).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
ref.keepSynced(true);
Toast.makeText(LoginActivity.this, "Please try again", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else {
Log.d("ZI", "Failed ", task.getException());
}
}
});
} else {
for (DataSnapshot ds : snapshot.getChildren()) {
users_from_database = (String) ds.child("username").getValue();
username_list.add(users_from_database);
StringBuilder stringBuilder = new StringBuilder();
for (String s : username_list) {
stringBuilder.append(s + "\n");
}
Log.d("ZI", stringBuilder.toString());
if (!username_list.contains(strUsername)) {
// do your job here , suppose send verification code to phone number
if (TextUtils.isEmpty(str_username) || TextUtils.isEmpty(str_fullname) || TextUtils.isEmpty(str_email) ||
TextUtils.isEmpty(str_password)) {
Toast.makeText(LoginActivity.this, "All fields are required!", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else if (str_password.length() < 6) {
Toast.makeText(LoginActivity.this, "Password must be over 6 characters.", Toast.LENGTH_SHORT).show();
pd.dismiss();
} else {
register(str_username, str_fullname, str_email, str_password);
}
} else {
username.setError("Username Exist");
pd.dismiss();
}
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
Log.d("ZI", "Failed");
}
});
}
});
我搜索了整个堆栈溢出,但大多数解决方案都需要知道节点名称才能运行。
即使在您的示例中,您也可以通过检查数据库中是否存在以下节点来检查用户是否存在:
root/users/$userName
在代码中应该是这样的:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("Users");
DatabaseReference userNameRef = usersRef.child("aaaaa");
userNameRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
@Override
public void onComplete(@NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
DataSnapshot snapshot = task.getResult();
if(snapshot.exists()) {
String fullName = snapshot.child("fullName").getValue(String.class);
Log.d("TAG", fullName);
} else {
Log.d("TAG", "The user doesn't exist!");
}
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
虽然 @TarikHuber 回答它会起作用,但请注意,在这种情况下,没有必要创建一个额外的节点来保存所有用户名,因为您的数据库结构已经这样做了。 因此,就检查用户是否存在而言:
root/users/$userName
这与以下内容完全相同:
root/usernames/$userName
由于实时数据库中的节点由键和值对表示,请注意键是唯一的。 所以你不可能有重复的节点。 由于每个节点都可以被认为是一个 Map。
但是,如果碰巧数据库中有多个用户共享相同的用户名,那么您应该使用以下代码行中的查询:
Query queryByUserName = usersRef.orderByChild("username").equalTo("aaaaa");
queryByUserName.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
@Override
public void onComplete(@NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot ds : task.getResult().getChildren()) {
if(ds.exists()) {
String fullName = ds.child("fullName").getValue(String.class);
Log.d("TAG", fullName);
} else {
Log.d("TAG", "The user doesn't exist!");
}
}
} else {
Log.d("TAG", task.getException().getMessage()); //Don't ignore potential errors!
}
}
});
根据您的屏幕截图,在这两种情况下,logcat 中的结果都是:
james
PS 虽然@ZahidIslam 的回答也可能有效,但下载整个“用户”节点并在客户端执行检查并不是最佳选择,因为它被认为非常昂贵。 这是对带宽和资源的浪费。
编辑:
根据你最后的评论:
我想你误会我了。 我想搜索 rootNodes 下的所有节点
您无法创建可以在数据库中的所有节点下进行搜索的查询。 但是,您可以下载整个数据库并在客户端进行过滤,但这样做成本很高,不推荐。
您拥有的最佳选择是为每个节点创建一个单独的查询,但前提是所有子节点都具有相同的字段。 或者您可以将用户仅保留在“用户”节点中(就像您现在所做的那样),我的答案中的代码将始终运行良好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.