1

So the issue I am having is I have a registration form in which users enter information (which also contains an email).

I have an onClick method called

public void onCreateAccount(View view);   

when the user clicks "Register", it validates the fields on the form.

public class Foo extends AppCompatActivity {
//OTHER PRIVATE MEMBERS
private EditText etEmail;
boolean isValid;
private DatabaseReference databaseUser = FirebaseDatabase.getInstance().getReference().child("User");

@Override
protected void onCreate(Bundle savedInstanceState) {
   //DOES SOME INITIALIZATION
}

public void onCreateAccount(View view){
   String email = etEmail.getText().toString().trim();

   if(validateEmail(email)){
      String id = databaseUser.push().getKey();
        User user = new User(id, email);
        databaseUser.child(user.getId()).setValue(user);
        Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
        intent.putExtra("isCreateAccount", true);
        startActivityForResult (intent,0);
   }
}

private boolean validateEmail(String email) {
   isValid = true; 
   databaseUser.orderByChild("email").equalTo(emailUserEntered).addListenerForSingleValueEvent(new ValueEventListener() {
                            @Override
                            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                                if(dataSnapshot.exists())
                                   isValid=false;

                            }

                            @Override
                            public void onCancelled(@NonNull DatabaseError databaseError) {

                            }
                        });
}

Before inserting the record into the firebase database, I want to first check if the email already exists prior to inserting. So a person typing email = a@mail.com would not allow so.

enter image description here

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Did my answer help you @YusufJama ? – PradyumanDixit Oct 25 '18 at 04:48
  • @PradyumanDixit refer to my comment in your answer below –  Oct 25 '18 at 04:50
  • @YusufJama follow this reference you will get help: https://stackoverflow.com/questions/47893328/checking-if-a-particular-value-exists-in-the-firebase-database – Rishav Singla Oct 25 '18 at 05:05
  • Most likely you're struggling with the fact that data is loaded from Firebase asynchronously. There is no way to simply return a boolean from `validateEmail`, since `onDataChange` fires after any `return` statement of `validateEmail`. See https://stackoverflow.com/a/50901184, https://stackoverflow.com/a/50435519 – Frank van Puffelen Oct 25 '18 at 05:50
  • @FrankvanPuffelen this is my problem...so is there a work around which will allow me to first validate? is the simplest way just to put all my validation into this onDataChange method? –  Oct 25 '18 at 05:50
  • @YusufJama, FrankvanPuffelen is right. Since data is loaded asynchronously, you should directly do the work from inside the `if(dataSnapshot.exists())`. You should directly display the toast from there only. – PradyumanDixit Oct 25 '18 at 06:07
  • Hi @YusufJama add your intent inside data change , because firebase query will take some time to get response , so check validation inside on dataChange and take action according to it – Shanmugam Oct 25 '18 at 06:10

4 Answers4

0

Stopping the user from logging in if such email exists should be simple and you may use a code like this to do so:

DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("User");

boolean flag=false;

databaseReference.orderByChild("email").equalTo(emailUserEntered).addListenerForSingleValueEvent(new ValueEventListener() {
                                @Override
                                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                                    if(dataSnapshot.exists())
                                       flag=true;

                                }

                                @Override
                                public void onCancelled(@NonNull DatabaseError databaseError) {

                                }
                            });
        return flag;                    

But if you want the user to be stopped from writing an email which is in database in mid-way, without authentication, it would be pretty difficult.

You'd have to run a check through the database letter by letter and not only this would decrease efficiency, it would be not so good looking at the end.

EDIT:

Data is loaded asynchronously from Firebase so you should be placing something like this right inside the if(dataSnapshot.exists()) to avoid the issue you're facing right now.

if(validateEmail(email)){
      String id = databaseUser.push().getKey();
        User user = new User(id, email);
        databaseUser.child(user.getId()).setValue(user);
        Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
        intent.putExtra("isCreateAccount", true);
        startActivityForResult (intent,0);
   }

else
  Toast(YourActivity.this, "Email already exists", LENGTH_LONG).show();
PradyumanDixit
  • 2,372
  • 2
  • 12
  • 20
0

Have an index on the email field. Then you can do a query to find by email.

That will improve performance as no need to loop through the children.

Something like:

orderByChild('email').equalTo(email).once('value').exist();
PradyumanDixit
  • 2,372
  • 2
  • 12
  • 20
ian1095
  • 551
  • 4
  • 8
0

Data is loaded from Firebase asynchronously, which makes it impossible to have a method like boolean validateEmail(String email) on Android. Loading data from the database would have to be a blocking operation to enable such a method, and Android doesn't allow blocking operations (as it would leave the phone inoperable).

So instead, you have to *either( move the code to create the user into validateEmail or pass in a custom interface that you then call once the result from the database is back. The code for that last one is below.

First we'll create a custom interface that you can implement anywhere where you need to check if a user already exists.

public interface UserExistsCallback {
  void onCallback(boolean value);
}

This interface can be as specific or generic as you want. It's very similar to Firebase's ValueEventListener, but this interface is just for your own use.

With this interface, we can define the validateEmail method like this:

private void validateEmail(String email, final UserExistsCallback callback) {
   isValid = true; 
   databaseUser.orderByChild("email").equalTo(emailUserEntered)
       .addListenerForSingleValueEvent(new ValueEventListener() {
           @Override
           public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
               callback.onCallback(dataSnapshot.exists())
           }

           @Override
           public void onCancelled(@NonNull DatabaseError databaseError) {
               throw databaseError.toException();
           }
       });
}

And then invoke it from onCreateAccount like this:

public void onCreateAccount(View view){
   String email = etEmail.getText().toString().trim();

   validateEmail(email), new UserExistsCallback() {
      public void onCallback(boolean exists) {
         if (!exists) {
            String id = databaseUser.push().getKey();
            User user = new User(id, email);
            databaseUser.child(user.getId()).setValue(user);
            Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
            intent.putExtra("isCreateAccount", true);
            startActivityForResult (intent,0);
         }
      })
   }
}

Also see many of the (linked) answers below:

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

This method is for auth only: firebase.auth().fetchProvidersForEmail("emailaddress@gmail.com")

Heartless Vayne
  • 904
  • 1
  • 8
  • 18