1

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.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

2 Answers2

1

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

}
Hasan Bou Taam
  • 4,017
  • 2
  • 12
  • 22
0

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:

  1. Defining an interface for your own callback:

    public interface UserExistsCallback {
      void onCallback(boolean value);
    }
    
  2. 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    
            }
        });
    }
    
  3. 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);
      }
    });
    
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807