Implement a read receipt feature in Firebase group

2020-05-19 08:00发布

问题:

I'd like to implement a 'Seen' feature in my Firebase group messaging app. Can you kindly advise the best and most efficient approach to take (working code will be appreciated)? For example, the app would show "Seen by 6" or "Seen by 15" on a group message.

Here's my project: https://github.com/firebase/friendlychat/tree/master/android

Here's the MainActivity: https://github.com/firebase/friendlychat/blob/master/android/app/src/main/java/com/google/firebase/codelab/friendlychat/MainActivity.java

回答1:

To achieve this, you need to add another node in your Firebase database named seenBy which must be nested under each messageId in meassage section. Your database should look like this:

Firebase-root
   |
   ---- messages
           |
           ---- messageId1
                   |
                   ---- meessage: "Hello!"
                   |
                   ---- timestamp: 1498472455940
                   |
                   ---- seenBy
                          |
                          ---- userUid1: John
                          |
                          ---- userUid2: Mary
                          |
                          ---- userUid3: George

Every time a new user opens a meesage, just add the uid and the name as explained above.

To implement Seen by 6 option, it's very easy. You just need to create a listener and use getChildrenCount() method like this:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference seenByRef = rootRef.child("messages").child(messageId).child("seenBy");
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        long seenBy = dataSnapshot.getChildrenCount();
        Lod.d("TAG", "Seen by: " + seenBy);
    }

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

To know whether a message has been opened or not, you need to add another field to your user section in which you need to add a boolean with the default value of false. This new section should look like this:

Firebase-root
   |
   ---- users
       |
       ---- userId1
           |
           ---- meessages
              |
              ---- messageId1: false
              |
              ---- messageId2: false
              |
              ---- messageId3: false

When a users opens that message, just set the value of that particular message from false to true, which means that the particular message has been opened. This is the code:

DatabaseReference openedRef = rootRef.child("users").child(userId).child("meessages").child("messageId1");
openedRef.setValue(true);

When you create a message, use push() method on the reference like this:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference messageRef = rootRef.child("meessages").push();
String messageKey = messageRef.getKey();

Having this key, you can use it in your DatabaseReference. In the same way you can use for the userId.

Hope it helps.



回答2:

Yeah it is possible, You can add a child seen_by to the message, whenever user views the message append the viewers userId to the seen_by , then by retrieving the userID and you can count the number of viewers and also you can see the list of viewed members too. The format should be

message:{
    FirebaseKey:{
        message:"hi",
        timestamp:1498472455940,
        seen_by:"abc,def,ghi" //users UID
      }
    }