Marvin-wtt
Marvin-wtt

Reputation: 499

How to listen to multiple children in Firebase?

I am currently trying to develop an app with which users can track their location. It is important that other users must not see the location of others not being in the group.

In order to listen to location updates from all users in the group I was wandering if attaching a ChildEventListener to each location is the most efficient way. It feels a bit strange to add so many listeners to the reference. (I think of storing the uid's in a list and applying a listener to the location child with the uid). As far as I know I can't set a Listener to the parent for security reason.

Is there any better way or is this the way to go?

{
    locations:{
        yY6qmwJLj69JGzgG:{
            "accuracy" : 23.429000854492188,
            "altitude" : 57,
            "latitude" : 3.4386667,
            "longitude" : 10.024,
            "speed" : 0,
            "time" : 1531114956000
        },
        msVYdaTy2DWcjuJ7:{
            ...
        },
        ...
    },
    groups:{
        users:{
            msVYdaTy2DWcjuJ7:true,
            yY6qmwJLj69JGzgG:true,
            ...
        },
        ...
    },
    ...
 }

I have currently following rules applied:

{
  "rules": {
    "groups" : {
      ".read" : false,
      ".write" : false,
      "$gid" : {
        ".read" : "auth != null",
        ".write" : "auth != null"
      }
    },
    "locations" : {
      ".read" : false,
      ".write" : false,
      "$uid" : {
        ".read" : "auth != null",
        ".write" : "auth.uid === $uid"
      }
    }
  }
}

My idea:

        for(String uid : mUserList) {
            mDatabaseReference.child("locations").child(uid).addValueEventListener(myListener);
        }

Upvotes: 1

Views: 2382

Answers (3)

Marvin-wtt
Marvin-wtt

Reputation: 499

I solved the problem by saving the structure to the following model

locations:{
    $groupID:{
        $userid:{
            ...
        },
        ...
    },
    ...
}

By doing so, I can listen to all locations with a single listener

Upvotes: 0

Raj
Raj

Reputation: 3001

The location of users can be seen only within the group. Eg-

Group A - User 1 
        - User 2

Group B - User 3
        - User 4

The user 1 and user 2 can see each other location because they are present in same group. But they are not allowed to look at locations of user 3 and 4 because of different groups.

For that the database structure should be like -

groups:{
            users:{
                user1:{
                "user_id" : x
                "grp_id": 11
                "grp" : "A"
                }

                user2:{
                "user_id": y
                "grp_id" : 11
                "grp" : "A"
                }

                user3:{
                "user_id" : z
                "grp_id" : 22
                "grp" : "B"
                }

                user4:{
                "user_id" : a
                "grp_id" : 22
                "grp": "B"
                }

            }
}

locations:{
        user_id:{
            "accuracy" : 23.429000854492188,
            "altitude" : 57,
            "latitude" : 3.4386667,
            "longitude" : 10.024,
            "speed" : 0,
            "time" : 1531114956000
            "grp_id" : 11
        },
        user_id:{
            ...
            "grp_id" : 22
        },
        ...
}

Suppose user 1 wants to access his location. Also he can access the location of user 2

String grp_id;
DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child(users).child(uid); // user 1 uid

reference.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
       for (DataSnapshot d : dataSnapshot.getChildren()) {
           grp_id = d.child("grp_id).getValue();
           fetchLocation(grp_id);

           // Here i came to know the group of user 1
       }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

You will get the group to which user 1 belongs, now from that group_id you can retrieve the location of all the people of that particular group using the method as done below. Also you can apply certain validations.

void fetchLocation(String grp_id) {

    DatabaseReference db = FirebaseDatabase.getInstance().getReference();

    Query query = db.child("locations").orderByChild("grp_id").equalTo(grp_id);
query.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {

    // Here you get the locations of users of group  
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

Upvotes: 1

Caspar Geerlings
Caspar Geerlings

Reputation: 1061

You should not be using the childEventListener on all children. Instead the childEventListener should be used on their parent.

Your idea: mDatabaseReference.child("locations").child(uid).addValueEventListener(myListener);

You should implement: mDatabaseReference.child("locations").addValueEventListener(myListener);

Upvotes: 0

Related Questions