Firebase Java Android检查是否因为子项与已存在于同一父项中的另一子项相同而未创建该子项

Firebase Java Android检查是否因为子项与已存在于同一父项中的另一子项相同而未创建该子项,java,firebase,firebase-realtime-database,children,Java,Firebase,Firebase Realtime Database,Children,我正在用java为android应用程序开发一个登录和注册系统。我使用firebase向用户注册电子邮件和密码,电子邮件、用户名和其他信息将在实时db firebase上形成一个继承结构,作为父级。用户id: 但是,我希望用户名是唯一的,这样,如果用户在父用户名中写入一个已经存在的用户名,他就会识别出还有另一个相同的子用户名。由于firebase不允许您使用相同的名称创建子项,因此我尝试执行以下操作: FirebaseDatabase.getInstance().getReference(&q

我正在用java为android应用程序开发一个登录和注册系统。我使用firebase向用户注册电子邮件和密码,电子邮件、用户名和其他信息将在实时db firebase上形成一个继承结构,作为父级。用户id:

但是,我希望用户名是唯一的,这样,如果用户在父用户名中写入一个已经存在的用户名,他就会识别出还有另一个相同的子用户名。由于firebase不允许您使用相同的名称创建子项,因此我尝试执行以下操作:

FirebaseDatabase.getInstance().getReference("Usernames").child(us.getText().toString()).setValue("Saved").addOnCompleteListener(new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(@NonNull Task<Void> task) {
                            Toast.makeText(getApplicationContext(), "Not same username", Toast.LENGTH_SHORT).show();
                        }
                    }).addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            Toast.makeText(getApplicationContext(), "same username", Toast.LENGTH_SHORT).show();
                        }
                    });
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference("Usernames").child(us.getText().toString());
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  void onDataChange(DataSnapshot snapshot) {
    if (snapshot.exists()) {
      // Username is already taken
    } else {
      // Username is available, add the data
    }
  }
});


完整代码:

您可以检查用户名是否存在,如下所示:

FirebaseDatabase.getInstance().getReference("Usernames").child(us.getText().toString()).setValue("Saved").addOnCompleteListener(new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(@NonNull Task<Void> task) {
                            Toast.makeText(getApplicationContext(), "Not same username", Toast.LENGTH_SHORT).show();
                        }
                    }).addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            Toast.makeText(getApplicationContext(), "same username", Toast.LENGTH_SHORT).show();
                        }
                    });
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference("Usernames").child(us.getText().toString());
rootRef.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  void onDataChange(DataSnapshot snapshot) {
    if (snapshot.exists()) {
      // Username is already taken
    } else {
      // Username is available, add the data
    }
  }
});


这可能是最简单的方法。如果您直接使用更新操作,它将覆盖现有值。

首先,您的代码不会抛出异常,表明用户名已被使用,因为您当前的规则授予对数据库的完全读写访问权限

{
“规则”:{
“.read”:“true”,
“.write”:“true”,
}
}
您不应简单地在每个用户名下存储
“Saved”
,而应存储用户ID。这将有助于以后删除用户帐户或更改其用户名。那你就需要。本文将介绍这两个步骤

“/usernames”:{
“bob”:“userId1”,
“frank”:“userId2”,
“c00lguy”:“userId3”
}
为了使您能够继续开发代码,同时在执行过程中收紧代码,您可以命名要锁定的特定树:

{
“规则”:{
//只有已登录的用户才能读取用户数据
//只有相关用户才能对其进行编辑
“用户”:{
“$uid”:{
“.read”:“auth!=null”,
.write:“auth!=null&&auth.uid==$uid”
},
},
//所有其他树都是全局可读写的
//TODO:删除此规则
“$其他”:{
“.read”:“true”,
.write:“正确”
}
}
}
因此,要将对
/usernames
的限制与当前数据库规则合并,您可以使用:

{
“规则”:{
“用户名”:{
“$username”:{
//世界可读
“.read”:正确,
//必须登录才能编辑,您只能声明免费用户名或删除拥有的用户名
“.write”:“auth!=null&(!newData.exists()| | auth.uid==newData.val())&(!data.exists()| | data.val()==auth.uid)”,
//仅限字符串
“.validate”:“newData.isString()”,
}
},
//所有其他树都是全局可读写的
//TODO:删除此规则
“$其他”:{
“.read”:“true”,
.write:“正确”
}
}
}
现在您已经保护了数据库,您可以在执行操作时声明用户名,如果您试图覆盖以前声明的用户名,它现在将抛出权限错误

重要的是,由于您正在使用,您需要首先检查任务是成功还是失败,因为在这两种情况下都将调用事件处理程序的
onComplete()
方法。这也消除了使用的必要性

String uid=FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseDatabase.getInstance()
.getReference(“用户名”)

.child(us.getText().toString())//我试图添加您的代码(看看问题,我用添加的代码更新了代码),但每次它都会给我“us ready ex”。。。我不明白why@pophome请共享数据库的完整屏幕截图,可能路径错误。@pophome我刚刚注意到我忘记删除setValue。你能试试更新的代码吗?好的,我试试你的更新代码我已经试过你的更新代码,但它会继续输出用户名的吐司不是在所有情况下都要的我现在应该把所有代码放在fAuth.createUserWithEmailAndPassword中吗?这是因为否则我无法获取uid。还是我错了?@pophome一旦用户成功通过身份验证,您现在可以在代码中的任何位置使用
FirebaseAuth.getInstance().getCurrentUser()
来获取当前登录的用户。您可以在
createUserWithEmailAndPassword
链中添加第一块代码,也可以使用
claimUsername(us.getText().toString()).addOnCompleteListener(…)
。这取决于你。就我个人而言,我倾向于使用函数来更好地理解代码。您建议的规则我应该如何插入它们?我还必须让读写保持真实吗?我已使用当前的rules@pophome我已经用与您当前规则相关的信息更新了答案。我用我得到的错误更新了问题。如果我粘贴规则,不要用答案中的代码修改原始问题中的代码,请保持您第一次提问时的状态。Ok@samthecodingman