Android Firebase Database check if Username is already use - java

hello i'm looking to create a way to check if the username is already in use or not.
The problem is that if the username is already taken the error is displayed correctly, but the user still registers ...
private boolean validateForm () {
boolean valid = true;
String username = rUsernameField.getText().toString();
String email = rEmailField.getText().toString();
if (TextUtils.isEmpty(email)) {
rEmailField.setError(getText(R.string.field_error));
valid = false;
} else {
rEmailField.setError(null);
}
String password = rPasswordField.getText().toString();
if (TextUtils.isEmpty(password)) {
rPasswordField.setError(getText(R.string.field_error));
valid = false;
} else {
rPasswordField.setError(null);
}
if (TextUtils.isEmpty(username)) {
rUsernameField.setError(getText(R.string.field_error));
valid = false;
validUsername = false;
} else {
rUsernameField.setError(null);
}
if (!validUsername) {
valid = false;
}
if (rCGUCheck.isChecked()) {
rCGUCheck.setError(null);
} else {
rCGUCheck.setError(getText(R.string.err_cgu));
valid = false;
}
return valid;
}
public void setValidUsername() {
String username = rUsernameField.getText().toString();
FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username").equalTo(username).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
validUsername = false;
Log.d(TAG, "false");
rUsernameField.setError("This username already exists");
} else {
validUsername = true;
Log.d(TAG, "true");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void signUp() {
Log.d(TAG, "signUp");
if (!validateForm()) {
return;
}
#Override
public void onClick (View v){
int i = v.getId();
if (i == R.id.regBtn) {
setValidUsername();
signUp();
}
therefore if one of the fields is not filled in, the user cannot register. But what I don't understand is why even if the username already exists the user can still register ^^
Thank's in advance.

Have one function called validateUser:
public void validateUser() {
//get string from editTexts
String username = rUsernameField.getText().toString();
String email = rEmailField.getText().toString();
String password = rPasswordField.getText().toString();
FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username").equalTo(username).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
//username is not available
rUsernameField.setError("This username already exists");
} else {
//username is available
//so check now if all is okay
if(!TextUtils.isEmpty(email) && !TextUtils.isEmpty(password) && !TextUtils.isEmpty(username) && rCGUCheck.isChecked()){
signUp();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
The signUp() method:
private void signUp(){
//sign up
Log.d(TAG, "signUp");
}
onclick() method
#Override
public void onClick (View v){
int i = v.getId();
if (i == R.id.regBtn) {
validateUser();
}

Your setValidUsername is an asynchronous operation. Data is loaded from Firebase asynchronously (like with most cloud APIs), since it may take some time to complete. While that is happening, you main code continues and your signUp method executes. Then when the data is available, your onDataChange is called and sets validUsername.
For a good example of this and a solution, see my answer here: getContactsFromFirebase() method return an empty list
For you this could mean:
Defining an interface for your own callback:
public interface UserExistsCallback {
void onCallback(boolean value);
}
Modify setValidUsername to take this callback as an argument, and call it:
public void isValidUsername(UserExistsCallback callback) {
String username = rUsernameField.getText().toString();
FirebaseDatabase.getInstance().getReference().child("users").orderByChild("username").equalTo(username).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
callback.onCallback(false);
rUsernameField.setError("This username already exists");
} else {
callback.onCallback(true);
Log.d(TAG, "true");
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException(); // never ignore errors
}
});
}
Call this new function and use the value in the callback:
isValidUsername(new UserExistsCallback() {
#Override
public void onCallback(boolean exists) {
System.out.println("User exists: "+exists);
}
});

Related

How to check if value exists in firebase databse

I have this Database:
I want to find out if a Email (value in database) already exists. So I have to iterate through each child of "email" and check if the value equals to the String inputMail.
I tried the following Code, but It doesn´t work, can anybody help me please? Thank u
final String input_mail = et_email.getText().toString();
DatabaseReference email = FirebaseDatabase.getInstance().getReference().child("email");
email.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String emailVal = ds.getValue(String.class);
if (emailVal.equals(input_mail)) {
//Toast exists
}
else {
//Toast not exists
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
In conclusion if I enter person1#m.de it should give out a toast that it exist
Here is a very easy way . Make your email as child . You have to replace the dot from the email and set it as child. (you can't use the email directly to a child)
static String encodeUserEmail(String userEmail) {
return userEmail.replace(".", ",");
}
static String decodeUserEmail(String userEmail) {
return userEmail.replace(",", ".");
}
Then you can easily match it like this :
final String input_mail = et_email.getText().toString();
DatabaseReference email = FirebaseDatabase.getInstance().getReference().child("email");
email.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(datasnapshot.child(input_mail).exits){
//Toast exists
}else {
//Toast not exists
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Trying to write same child to firebase twice

I am trying to execute this if statement so the value 'Like' with the unique id is written to the database twice. The line of code is:
mDatabaseChemRef.child(uploadCurrent.getNumber()).child(mAuth.getCurrentUser().getUid()).setValue("Like");
and the database is stored like so:
{
"467" : {
"4ulBYMRcP4WbhTCFXHSTNwX2yPU2" : "Like"
}
}
So essentially I want the "Like" along side the same unique ID to be written twice rather than once. Below is the full code. So when the user clicks the like button I want it to like twice rather than once is there a way to write this line twice?
holder.mLikebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mProcessTechLike = true;
mDatabaseTechRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(uploadCurrent.getCategory().equals("Technology")) {
if (mProcessTechLike) {
if (dataSnapshot.child(uploadCurrent.getNumber()).hasChild(mAuth.getCurrentUser().getUid())) {
//delete like
dataSnapshot.child(uploadCurrent.getNumber()).child(mAuth.getCurrentUser().getUid()).getRef().removeValue();
mProcessTechLike = false;
Toast.makeText(mContext, "Vote Retracted", Toast.LENGTH_LONG).show();
holder.mLikebtn.setColorFilter(null);
} else {
Resources res = mContext.getResources();
final int newColor = res.getColor(R.color.new_color);
holder.mLikebtn.setColorFilter(newColor, Mode.SRC_ATOP);
mDatabaseTechRef.child(uploadCurrent.getNumber()).child(mAuth.getCurrentUser().getUid()).setValue("Like");
mProcessTechLike = false;
Toast.makeText(mContext, "Vote Counted", Toast.LENGTH_LONG).show();
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Single Value Listener happening more than once

I have a simple multiplayer game for my app, and the game play is super simple. Each player has to press 'ready' and then the game starts.
Once both players are ready, gameStarted is set to true and the gameplay (which is not controlled by the players at all) is supposed to happen. This works, but the problem is it happens more than once on a loop. This is the value event listener I have in place.
games.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot) {
HomePage.getCurrentGameID(new HomePage.CallbackID() {
#Override
public void onSuccess(String currentGameID) {
if (dataSnapshot.child(currentGameID).child("player1").child("ready").getValue().equals(true)
&& dataSnapshot.child(currentGameID).child("player2").child("ready").getValue().equals(true)) {
counter.run();
}
if (dataSnapshot.child(currentGameID).child("gameStarted").getValue().equals(true) &&
dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(1)) {
headsOrTails.setText("Heads");
Log.i("FlipCoin", ";;happened");
flipHeads();
getResults();
endGame();
} else if (dataSnapshot.child(currentGameID).child("gameStarted").getValue().equals(true) &&
dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(2)) {
headsOrTails.setText("Tails");
Log.i("FlipCoin", ";;happened");
flipTails();
getResults();
endGame();
}
Here is my getResults() method. I am putting it here to show that I have another value event listener being called from my addListenerForSingleValueEvent that I have shown above
private void getResults() {
games.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull final DataSnapshot dataSnapshot) {
HomePage.getCurrentGameID(new HomePage.CallbackID() {
#Override
public void onSuccess(final String currentGameID) {
final String horT1 = dataSnapshot.child(currentGameID).child("player1").child("horT").getValue().toString();
final String horT2 = dataSnapshot.child(currentGameID).child("player2").child("horT").getValue().toString();
final double wager = Double.parseDouble(dataSnapshot.child(currentGameID).child("wager").getValue().toString());
HomePage.getUserPosition(new HomePage.CallbackPosition() {
#Override
public void onSuccess(int position) {
if(position == 1) {
if(horT1.equals("Heads") && dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(1)
|| horT1.equals("Tails") && dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(2)) {
getWinner(FirebaseAuth.getInstance().getUid(), wager);
} else {
getLoser(FirebaseAuth.getInstance().getUid(), wager);
}
}
if(position == 2) {
if(horT2.equals("Heads") && dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(1)
|| horT2.equals("Tails") && dataSnapshot.child(currentGameID).child("horT").getValue(Integer.class).equals(2)) {
getWinner(FirebaseAuth.getInstance().getUid(), wager);
} else {
getLoser(FirebaseAuth.getInstance().getUid(), wager);
}
}
if(dataSnapshot.child(currentGameID).child("gameFinished").getValue().equals(true)) {
//games.child(currentGameID).removeValue();
}
endGame();
}
});
}
});
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
});
I thought that setting it as a Single value event listener would make it only happen once, but I have a log in there that when I run the game, is called on a loop.
How can I make this event just happen one time?

Android Studio firebase database wait for read before adding new values

I have a database in which I store users and I want to check if a user exists before adding a new one so I don't overwrite.
I have a function that goes through database records and returns a boolean value if it finds or doesn't find the user.
public boolean checkUserExists(final String emailAddress, final String emailDomain){
DatabaseReference myRef = database.getReference("Users");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot mydata : dataSnapshot.getChildren()){
User user = mydata.getValue(User.class);
if (user.getEmailAddress().equals(emailAddress) &&
user.getEmailDomain().equals(emailDomain)){
userExists = true;
break;
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return userExists;
}
The way I am currently trying to do the check is like this:
if (!(registerRepo.checkUserExists(emailAddress, emailDomain))){
User user = new User(firsName, lastName, emailAddress, emailDomain);
registerRepo.writeUser(user);
} else {
Toast toast = Toast.makeText(getBaseContext(), "User exists", Toast.LENGTH_SHORT);
toast.show();
}
The problem is that it doesn't wait for the read and goes ahead and creates a new record (I'm using push so it creates the same record under a new push ID). I've seen that firebase has such a thing called transaction handler and I think that is what I need to use but the documentation didn't help me and I've looked at others asking sort-of the same question here but couldn't figure out a solution so please, if you can explain how to do it and not redirect me to other question I'd be grateful.
Firebase requests are asynchronous.
So you need to add a callback in your checkUserExists if you want to do some code after getting the result from database.
For example :
public interface OnCheckUserExist {
void exist();
void notExist();
}
registerRepo.checkUserExists(emailAddress, emailDomain, new OnCheckUserExist(){
#Override
public void exist(){
Toast toast = Toast.makeText(getBaseContext(), "User exists",Toast.LENGTH_SHORT);
toast.show();
}
#Override
public void notExist(){
User user = new User(firsName, lastName, emailAddress, emailDomain);
registerRepo.writeUser(user);
}
})
public void checkUserExists(final String emailAddress, final String emailDomain, OnCheckUserExist onCheckUserExist){
DatabaseReference myRef = database.getReference("Users");
myRef.addValueEventListener(new ValueEventListener() {
boolean userExist;
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot mydata : dataSnapshot.getChildren()){
User user = mydata.getValue(User.class);
if (user.getEmailAddress().equals(emailAddress) &&
user.getEmailDomain().equals(emailDomain)){
onCheckUserExist.exist();
userExist = true;
break;
}
}
if (!userExist){
onCheckUserExist.notExist();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
You need to put your code inside onDataChange like this
public boolean checkUserExists(final String emailAddress, final String emailDomain){
DatabaseReference myRef = database.getReference("Users");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot mydata : dataSnapshot.getChildren()){
User user = mydata.getValue(User.class);
if (user.getEmailAddress().equals(emailAddress) &&
user.getEmailDomain().equals(emailDomain)){
userExists = true;
break;
}
}
if (userExists) {
User user = new User(firsName, lastName, emailAddress, emailDomain);
registerRepo.writeUser(user);
} else {
Toast toast = Toast.makeText(getBaseContext(), "User exists", Toast.LENGTH_SHORT);
toast.show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return userExists;
}
Though I would suggest you to refactor this one by creating separate functions. :)

How to move Firebase child from one node to another in Android?

I am working on a project where user request for our valet services and on the other end valet accepts request.
I am using using Firebase as backend and on request customer uid is save on 'request' child.
When valet accepts request, customer uid should move from 'request' node to 'on progress' node.
How can i do that?
I recommend using this :
public void moveFirebaseRecord(Firebase fromPath, final Firebase toPath)
{
fromPath.addListenerForSingleValueEvent(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
toPath.setValue(dataSnapshot.getValue(), new Firebase.CompletionListener()
{
#Override
public void onComplete(FirebaseError firebaseError, Firebase firebase)
{
if (firebaseError != null)
{
System.out.println("Copy failed");
}
else
{
System.out.println("Success");
}
}
});
}
#Override
public void onCancelled(FirebaseError firebaseError)
{
System.out.println("Copy failed");
}
});
}
This come from this source : https://gist.github.com/katowulf/6099042 . I used it several times in my JavaEE code and also in my android app.
You pass your fromPath and toPath. This is a copy tought and not a move, so the original will remain at his original place too. If you would like to delete, you can do a set value on the fromPath just after the System.out.println("Success"); .
As of compile firebase-database:11.0.1, this is the same function with the new class references (https://firebase.google.com/support/guides/firebase-android July 05 2017)
private void moveGameRoom(final DatabaseReference fromPath, final DatabaseReference toPath) {
fromPath.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
toPath.setValue(dataSnapshot.getValue(), new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError firebaseError, DatabaseReference firebase) {
if (firebaseError != null) {
System.out.println("Copy failed");
} else {
System.out.println("Success");
}
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
If you want to perform a move which also erases the original, you might make use of the following snippet:
// In this piece of code, "fromPath" and "toPath" parameters act like directories.
private void removeFromFirebase(final DatabaseReference fromPath, final DatabaseReference toPath, final String key) {
fromPath.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
// Now "DataSnapshot" holds the key and the value at the "fromPath".
// Let's move it to the "toPath". This operation duplicates the
// key/value pair at the "fromPath" to the "toPath".
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
toPath.child(dataSnapshot.getKey())
.setValue(dataSnapshot.getValue(), new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
Log.i(TAG, "onComplete: success");
// In order to complete the move, we are going to erase
// the original copy by assigning null as its value.
fromPath.child(key).setValue(null);
}
else {
Log.e(TAG, "onComplete: failure:" + databaseError.getMessage() + ": "
+ databaseError.getDetails());
}
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e(TAG, "onCancelled: " + databaseError.getMessage() + ": "
+ databaseError.getDetails());
}
});
}
you can listen to value event on your child you want to copy it ,, and #onDataChange get reference of new child and set value dataSnapshot to this child like below sample code
FirebaseDatabase.getInstance().getReference("childYouWantToCopy")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
FirebaseDatabase.getInstance().getReference("ChildCopyTo").setValue(dataSnapshot.getValue());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});

Categories