Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chat message with Google Firebase Realtime Database architecture with Unread Message counter and Last Message

I'm creating a chat section for android apps. By using Google Firebase. Following task already completed

Create chat node 2. Separate particular chat thread using two users information. 3. Read all message for single chat thread.

Now my question is below. 1. How to retrieve last message by single chat thread. 2. How to create a database where i can get counter of unread message counter.

Attachment of my chat database and objective below.

Current objective. enter image description here

Already done.

enter image description here

Firebase database architecture.

enter image description here

Now how it will be easier for me to create database for make solution this problem.

like image 651
Mahmudul Avatar asked Aug 13 '16 18:08

Mahmudul


2 Answers

Firebase has it's own example project for building a Chat platform, Firechat. The project is well explained in it's doc. The data structure they used can be seen at the end of the doc. You can use their data structure. But for your case, you probably don't have any moderator, so we can make it a little simple than that.

So, you can organize it like this:

main-data
|__messageThread  (all data about msgs)
|  |__threadId      (unique id for msg thread)
|     |__chatId     (unique id for chat msgs)
|        |__userId
|        |__userName
|        |__chatMessage
|        |__chatTimestamp
|
|__messageThreadMetadata  
|  |__threadId      
|     |__createdAt     
|     |__createdByUserId
|     |__threadId
|     |__threadName
|     |__threadType (public/private)
|     |__lastChatId (id for last chat, use this to lookup in messageThread)
|
|__users  
|  |__userId      
|     |__userId
|     |__userName
|     |__activeThreads (list of ids of active threads used by user)
|
|__unseenMsgCountData  
|  |__threadId       
|     |__userId
|     |__unseenMsgCount

To get back to your question:

  1. How to get last message in a thread? Please use the node lastChatId in a thread and use it to look up the respective chatMessage.

  2. How to get unseen message count in a thread for an user? This is a data that is subjective to each thread and each user. A same thread may have two or more users, each having different unseen message count. So, you can use unseenMsgCountData where you can check across a threadId and userId. Whenever anyone posts a chat, increment the unseen msg counter by 1 in that thread for other users, who has the chat thread closed (use the activeThreads list from users to track whether he is actively in the thread or not). DO NOT increase the counter for him though, this msg is not his own unseen msg). When any other user opens that thread, reset the value to zero for him.

Hope this helps. Knock here if any further explanation or help is needed.

like image 124
Riddhiman Adib Avatar answered Nov 10 '22 00:11

Riddhiman Adib


this is my workaround.

enter image description here

as you can see i am making two reference one for message and second recent is for user list.

whenever i tap on user list and open my chat page, In my chat page i m checking condition for receiver id and send status and count to recent refrence in onCreate() of chat page, like this.

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);

        uid = pref.getString("uid", null);
        sender_name = pref.getString("first_name", null);

        Bundle bundle = getIntent().getExtras();
        if(bundle != null && !bundle.isEmpty()){
            recevier_name = bundle.getString("uname");
            receiver_id = bundle.getString("UserId");
        }else {
            recevier_name = "Admin";
            receiver_id = "1";
        }

        chat_date = listAdapter.SIMPLE_DATE_FORMAT.format(new Date().getTime());
        if (Integer.parseInt(uid) < Integer.parseInt(receiver_id)) {
            value = String.valueOf(uid + "--*--" + receiver_id);
        } else {
            value = String.valueOf(receiver_id+"--*--"+uid);
        }

myRef1 = database.getReferenceFromUrl("https://firebaseio.com/messages/"+value);

myRef2 = database.getReferenceFromUrl("https://firebaseio.com/recents/"+value);

    myRef2.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if(dataSnapshot != null){
                Map map1 = (Map) dataSnapshot.getValue();
                if(map1 != null){
                    String rec_id = (String) map1.get("recever_id");
                    if(rec_id.equals(uid)){
                        myRef2.getRef().child("count").setValue("0");
                        myRef2.getRef().child("status").setValue("online");
                    }
                }

            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

    getChat();
}

so everytime when i open my chat my status is online if receiver_id is my_id.

now in chat button click i m checking for count if status is not online, like this.

private ImageView.OnClickListener clickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if(v==enterChatView1)
            {
                message_text = chatEditText1.getText().toString();
                final Map<String, String> map = new HashMap<String, String>();
                map.put("sender_id", uid );
                map.put("recever_id", receiver_id);
                map.put("sender_name", sender_name);
                map.put("recevier_name", recevier_name);
                map.put("text", message_text);
                map.put("text_id", uid);
                map.put("date", chat_date);
                myRef1.push().setValue(map);
              //  myRef2.setValue(map);
               // sendMessage(chatEditText1.getText().toString(), chat_date, UserType.OTHER);

                myRef2.addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if(dataSnapshot != null){
                            Map map1 = (Map) dataSnapshot.getValue();
                            if(map1 != null){
                                String status = (String)map1.get("status");
                                if(map1.containsKey("count")){
                                    if(!status.equals("online")) {
                                        String count = (String) map1.get("count");
                                        int val = Integer.parseInt(count);
                                        map.put("count", String.valueOf(++val));
                                        map.put("status", "offline");
                                        myRef2.setValue(map);
                                        Log.d("VALUE", "YES" + val);
                                    }else {
                                        map.put("count", String.valueOf(0));
                                        map.put("status", "online");
                                        myRef2.setValue(map);
                                        Log.d("VALUE", "No");
                                    }
                                }else {
                                    map.put("count", String.valueOf(1));
                                    map.put("status", "offline");
                                    myRef2.setValue(map);
                                    Log.d("VALUE", "No");
                                }
                            }else {
                                map.put("count", String.valueOf(1));
                                map.put("status", "offline");
                                myRef2.setValue(map);
                                Log.d("VALUE", "first time");
                            }
                        }else {
                            map.put("count", String.valueOf(1));
                            map.put("status", "offline");
                            myRef2.setValue(map);
                            Log.d("VALUE", "first time");
                        }
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });


            }



            chatEditText1.setText("");

        }
    };

and at last when you close your chat page. add status offline to recent in onBackPress() event, like this.

@Override
    public void onBackPressed() {

            myRef2.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    if(dataSnapshot != null){
                        Map map1 = (Map) dataSnapshot.getValue();
                        if(map1!= null){
                            String rec_id = (String) map1.get("recever_id");
                            if(rec_id.equals(uid)){
                                myRef2.getRef().child("count").setValue("0");
                                myRef2.getRef().child("status").setValue("offline");

                            }
                        }
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });
            finish();
            this.overridePendingTransition(R.anim.left_in,
                    R.anim.left_out);  
    }
like image 39
Sagar Chavada Avatar answered Nov 09 '22 23:11

Sagar Chavada