Asked  7 Months ago    Answers:  5   Viewed   85 times

I am making an Android application using Firebase realtime database. When a new user registers on my app, that user's data is saved in the Firebase database.

A user has to provide the following details to register:

  1. Full Name
  2. Email
  3. Username
  4. Password

Database Structure

enter image description here

Whenever a new user tries to register, I have to make sure that each user's username is unique so I check the database if the username entered by the user already exists in the database or not.

To do this, I wrote the following method:

private boolean usernameExists(String username) {
     DatabaseReference fdbRefer = FirebaseDatabase.getInstance().getReference("Users/"+username);
     return (fdbRefer != null);
}

My logic behind this method is that if getReference method cannot find reference to the specified path, it will return null so that I can return whether fdbRefer is null or not. If fdbRefer is null, then it means that username doesn't exist in the database.

Problem

Problem with this method is that it always returns true whether the entered username exists in the database or not. Which led me to believe that fdbRefer is never null.

This brings me to my question...

Question

What does getReference method return when it can't find the specified path in the firebase database and what's the correct way to check if the username already exists in the database or not?

 Answers

57

To check a existence of user, please use the below code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userNameRef = rootRef.child("Users").child("Nick123");
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if(!dataSnapshot.exists()) {
            //create new user
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
    }
};
userNameRef.addListenerForSingleValueEvent(eventListener);

You can also use a Query to achieve the same thing like this:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("Users").orderByChild("userName").equalTo("Nick123");
query.addValueEventListener(/* ... */);

This is another approach which is looping through the entire Users node but is not just using a direct reference to a single user. This option is more likely to be used when you are using as a unique identifier beteeen users the uid instead of the user name (as you do right now). So if your database structure might looks similar to this:

Firebase-root
   |
   --- Users
        |
        --- uid
             |
             --- userName: "Test User"
             |
             --- emailAddress: "user@email.com"

The second solution is the recommended one.

There is also another solution which involves you to create another node named userNames, in which you can hold only the unique user names. Please also find below the corresponding security rules:

"Users": {
  "$uid": {
    ".write": "auth !== null && auth.uid === $uid",
    ".read": "auth !== null && auth.provider === 'password'",
    "userName": {
      ".validate": "
        !root.child('userNames').child(newData.val()).exists() ||
        root.child('userNames').child(newData.val()).val() == $uid"
    }
  }
}

But since in this case, your user name is already the name of the node, I recommend you go ahead with the first one.

Tuesday, June 1, 2021
 
muffe
answered 7 Months ago
77

To let the FirebaseRecyclerAdapter and FirebaseListAdapter show the data on the activity

You need to use this:

@Override
protected void onStart() {
super.onStart();
adapter.startListening();
}


@Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}

Since FirebaseListAdapter uses a listener to check for changes in the firebase database, then to being listening for data you need to add adapter.startListening() inside the onStart() to be able to show the data in the listview.

Then inside onStop() (when activity is stopped), you can use adapter.stopListening() to remove the listener and the data in the adapter.

Check this for more info: Adapter LifeCycle

Note:

If after using the above, you get a nullpointexception or cannot resolve symbol, you have to declare adapter as global variable and please check the below answer: Error in startListening()

Tuesday, June 1, 2021
 
msg
answered 7 Months ago
msg
43

The problem is that you are creating the property "mobile_phone" as a String and on Firebase it is a Long type.

Change:

private String mobile_phone;

To:

private Long mobile_phone;
Thursday, June 24, 2021
 
NaeiKinDus
answered 6 Months ago
62

Create an object that will hold your data, eg. ClientData
Create a method for fetching all data from the database

public List<ClientData> selectAll() {
   List<ClientData> list = new ArrayList<ClientData>();
   Cursor cursor = this.myDataBase.query(TABLE_NAME, new String[] { "userID, clientName" },
   null, null, null, null, null);
   if (cursor.moveToFirst()) {
        do {
           list.add(new ClientData(cursor.getString(0), cursor.getString(1)));
         } while (cursor.moveToNext());
   }
   if (cursor != null && !cursor.isClosed()) {
         cursor.close();
   }
   return list;
}

Before executing your insert statements, fetch all data and then check if data exists:

if (!list.contains(clientData)) {
    executeInsert();
}

I am not sure if SQLite supports stored procedures, but if it does, you could write a stored procedure for that as well.

Friday, August 6, 2021
 
leetwinski
answered 4 Months ago
83

This is not the best practice when it comes to save user details into the database. First, you should implement Firebase Authentication and then in order to check if a user exist in your database, you should use the following lines of code:

String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("users").child(uid);
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
    if(!dataSnapshot.exists()) {
        //create new user
    }
}

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
uidRef.addListenerForSingleValueEvent(eventListener);

So the key for solving this problem is to call the child() method and pass the uid as an argument instead of calling the push() method that generates an random unique identifier.

Monday, November 22, 2021
 
JakeGR
answered 2 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share