저번 포스팅에서 실시간으로 메시지를 주고 받는 기능까지 추가해보았습니다. 그러나 현재 상태로는 새로운 메시지가 도착했는지 알 수 없습니다. 그래서 이번 포스팅에서는 새로운 메시지가 있음을 알려주는 기능과 메시지를 읽지 않은 유저의 수를 표시하는 기능을 추가해보겠습니다.
각 채팅방마다 본인이 읽지 않은 메시지의 개수를 확인할 수 있는 기능을 추가하자.
① MessageModel에 readerUid 필드를 추가한다.
val readerUids: MutableMap<String, Boolean> = mutableMapOf(),
② ChatRoom에 unreadCount 필드를 추가한다.
val unreadCount : Int? = 0
③ chat_listview_item.xml 파일을 아래와 같이 수정한다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/list_border"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp">
        <TextView
            android:id="@+id/lvChatRoomName"
            android:text="ChatRoom Name"
            android:textStyle="bold"
            android:textColor="#000000"
            android:textSize="20sp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="10dp"
            android:layout_marginTop="10dp"
            android:layout_marginBottom="5dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <FrameLayout
            android:id="@+id/unreadMessageContainer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:visibility="gone"
            android:background="@drawable/message_box">
            <TextView
                android:id="@+id/unreadMessageCountTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="0"
                android:gravity="center"
                android:layout_marginHorizontal="8dp"
                android:layout_marginVertical="5dp"
                android:textSize="20sp"
                android:textColor="#000000" />
        </FrameLayout>
    </LinearLayout>
    <TextView
        android:id="@+id/lvUserListArea"
        android:text="User List"
        android:textSize="15sp"
        android:layout_marginHorizontal="40dp"
        android:layout_marginBottom="20dp"
        android:maxWidth="170dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

④ ChatListFragment의 getChatRoomList를 아래와 같이 수정하고, getUnreadMessageCount 메서드를 추가한다.
private fun getChatRoomList() {
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                chatRoomList.clear()
                for (datamModel in dataSnapshot.children) {
                    val chatRoom = datamModel.getValue(ChatRoom::class.java)
                    chatRoomList.add(chatRoom!!)
                }
                for(chatRoom in chatRoomList) {
                    getUnreadMessageCount(chatRoom.chatRoomId!!)
                }
                listViewAdapter.notifyDataSetChanged()
            }
            override fun onCancelled(databseError: DatabaseError) {
                Log.w("MyMessage", "onCancelled", databseError.toException())
            }
        }
        FirebaseRef.chatRoom.child(FirebaseAuthUtils.getUid()).addValueEventListener(postListener)
    }
    private fun getUnreadMessageCount(chatRoomId : String) {
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                var count = 0
                for (datamModel in dataSnapshot.children) {
                    val uidList = datamModel.child("readerUid").getValue(object : GenericTypeIndicator<MutableMap<String, Boolean>>() {})
                    if (uidList != null) {
                        Log.d("readerUid", uidList.toString())
                        if (!uidList.containsKey(FirebaseAuthUtils.getUid())) {
                            // readerUid에 내 uid가 없으면
                            count++
                        }
                    }
                }
                FirebaseRef.chatRoom.child(FirebaseAuthUtils.getUid()).child(chatRoomId).child("unreadCount").setValue(count)
            }
            override fun onCancelled(databaseError: DatabaseError) {
                Log.w("MyMessage", "onCancelled", databaseError.toException())
            }
        }
        FirebaseRef.message.child(chatRoomId).addValueEventListener(postListener)
    }
⑤ ChatRoomAdapter를 아래와 같이 수정한다.
class ChatRoomAdapter(private val context: Context, private val dataList : List<ChatRoom>) : BaseAdapter() {
    override fun getCount(): Int {
        return dataList.size
    }
    override fun getItem(position: Int): Any {
        return dataList[position]
    }
    override fun getItemId(position: Int): Long {
        return position.toLong()
    }
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        var convertView = convertView
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.chat_listview_item, parent, false)
        }
        val listViewChatRoomName = convertView?.findViewById<TextView>(R.id.lvChatRoomName)
        val listViewUserList = convertView?.findViewById<TextView>(R.id.lvUserListArea)
        val listViewUnreadCount = convertView?.findViewById<TextView>(R.id.unreadMessageCountTextView)
        val unreadMessageContainer = convertView?.findViewById<FrameLayout>(R.id.unreadMessageContainer)
        listViewUnreadCount!!.text = dataList[position].unreadCount.toString()
        val unreadCount = listViewUnreadCount!!.text.toString().toInt()
        if (unreadCount > 0) {
            unreadMessageContainer!!.visibility = View.VISIBLE
            listViewUnreadCount.visibility = View.VISIBLE
        } else {
            unreadMessageContainer!!.visibility = View.GONE
            listViewUnreadCount.visibility = View.GONE
        }
        listViewChatRoomName!!.text = dataList[position].roomName
        listViewUserList!!.text = dataList[position].userList
        return convertView!!
    }
}
⑥ 채팅방에 들어가면 모든 메시지의 readerUid Mutable Map에 본인의 UID를 추가해야 한다. ChatRoomActivity를 아래와 같이 수정한다.
class ChatRoomActivity : AppCompatActivity() {
    lateinit var count : String
    lateinit var messageAdapter : MessageAdapter
    lateinit var recyclerView : RecyclerView
    val messageList = mutableListOf<MessageModel>()
    val readerUidMap = mutableMapOf<String, Boolean>()
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_chat_room)
        readerUidMap[FirebaseAuthUtils.getUid()] = true
        val roomName = findViewById<TextView>(R.id.chatRoomName)
        val nickNameList = findViewById<TextView>(R.id.nickNameList)
        val inviteBtn = findViewById<Button>(R.id.invite)
        val userCount = findViewById<TextView>(R.id.userCount)
        // Intent로부터 데이터를 가져옴
        val chatRoomName = intent.getStringExtra("chatRoomName")
        roomName.text = chatRoomName
        val roomId = intent.getStringExtra("chatRoomId")
        val chatRoomId = roomId
        val userList = intent.getStringExtra("userList")
        nickNameList.text = userList
        CoroutineScope(Dispatchers.IO).launch {
            val response = getUserCount(chatRoomId!!)
            Log.d("userCount", response.toString())
            if (response.isSuccess) {
                count = response.result.toString()
                userCount.text = count
            } else {
                Log.d("UserListFragment", "유저의 정보를 불러오지 못함")
            }
        }
        recyclerView = findViewById<RecyclerView>(R.id.messageRV)
        messageAdapter = MessageAdapter(this, messageList)
        recyclerView.adapter = messageAdapter
        recyclerView.layoutManager = LinearLayoutManager(this)
        getMessageList(chatRoomId!!)
        Log.d("MessageList", messageList.toString())
        inviteBtn.setOnClickListener {
            val intent = Intent(this, InviteActivity::class.java)
            intent.putExtra("chatRoomId", chatRoomId)
            intent.putExtra("chatRoomName", chatRoomName)
            intent.putExtra("nickNameList", userList)
            startActivity(intent)
        }
        val participantBtn = findViewById<ImageView>(R.id.participants)
        participantBtn.setOnClickListener {
            val intent = Intent(this, ParticipantsActivity::class.java)
            intent.putExtra("chatRoomId", chatRoomId)
            startActivity(intent)
        }
        val message = findViewById<TextInputEditText>(R.id.message)
        val sendBtn = findViewById<ImageView>(R.id.send)
        lateinit var myNickName : String
        lateinit var myProfileUrl : String
        lateinit var messageModel: MessageModel
        val myUid = FirebaseAuthUtils.getUid()
        sendBtn.setOnClickListener {
            val contents = message.text.toString()
            val sendTime = getSendTime()
            CoroutineScope(Dispatchers.IO).launch {
                val response = getUserInfo(myUid)
                if (response.isSuccess) {
                    myNickName = response.result?.nickName.toString()
                    myProfileUrl = response.result?.imgUrl.toString()
                    val readerUids = mutableMapOf<String, Boolean>()
                    messageModel = MessageModel(myUid, myNickName, myProfileUrl, contents, sendTime, readerUids)
                    FirebaseRef.message.child(chatRoomId!!).push().setValue(messageModel)
                } else {
                    Log.d("ChatRoomActivity", "유저의 정보를 불러오지 못함")
                }
            }
            message.text?.clear()
        }
    }
    override fun onBackPressed() {
        readerUidMap.remove(FirebaseAuthUtils.getUid())
        val intent = Intent(this, MainActivity::class.java)
        startActivity(intent)
    }
    private suspend fun getUserCount(roomId: String) : BaseResponse<String> {
        return RetrofitInstance.chatApi.getUserCount(roomId)
    }
    private suspend fun getUserInfo(uid: String): BaseResponse<GetUserRes> {
        return RetrofitInstance.myPageApi.getUserInfo(uid)
    }
    //메시지 보낸 시각 정보 반환
    @RequiresApi(Build.VERSION_CODES.O)
    private fun getSendTime(): String {
        try {
            val localDateTime = LocalDateTime.now()
            val dateTimeFormatter = DateTimeFormatter.ofPattern("M/d  h:mm  a")
            return localDateTime.format(dateTimeFormatter)
        } catch (e: Exception) {
            e.printStackTrace()
            throw Exception("시간 정보를 불러오지 못함")
        }
    }
    private fun getMessageList(chatRoomId: String) {
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                messageList.clear()
                val newMessages = mutableListOf<MessageModel>() // 새로운 메시지를 저장할 리스트 생성
                for (dataModel in dataSnapshot.children) {
                    val messageModel = dataModel.getValue(MessageModel::class.java)
                    if (messageModel != null) {
                        if (messageModel.senderUid != FirebaseAuthUtils.getUid()) {
                            messageModel.viewType = MessageModel.VIEW_TYPE_YOU
                        }
                        // 새로운 메시지 ID 생성
                        val messageId = dataModel.key
                        if (messageId != null) {
                            FirebaseRef.message.child(chatRoomId!!).child(messageId).child("readerUid")
                                .updateChildren(readerUidMap as Map<String, Boolean>)
                        }
                        newMessages.add(messageModel)
                    }
                }
                messageList.addAll(newMessages)
                messageAdapter.notifyDataSetChanged()
                Log.d("MessageList", messageList.toString())
                recyclerView.post {
                    recyclerView.scrollToPosition(recyclerView.adapter?.itemCount?.minus(1) ?: 0)
                }
            }
            override fun onCancelled(databaseError: DatabaseError) {
                Log.w("MyMessage", "onCancelled", databaseError.toException())
            }
        }
        FirebaseRef.message.child(chatRoomId).addValueEventListener(postListener)
    }
}
코드를 실행시켜보면, 읽지 않은 메시지의 개수가 실시간으로 추가되는 것을 확인해 볼 수 있을 것이다. 또한 채팅방에 들어갔다가 나오면, 채팅방의 모든 메시지를 읽은 것으로 처리해야 한다.

① message_recycler_view_item.xml 파일을 아래와 같이 수정한다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/messageContentsArea"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="35dp"
            android:layout_marginEnd="8dp"
            android:background="@drawable/message_box"
            android:ellipsize="end"
            android:maxWidth="230dp"
            android:padding="10dp"
            android:text="my text message"
            android:textSize="15sp"
            app:layout_constraintEnd_toStartOf="@+id/messageProfileArea"
            app:layout_constraintTop_toTopOf="parent" />
        <FrameLayout
            android:id="@+id/unreadUserCountContainer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/messageContentsArea">
            <TextView
                android:id="@+id/unreadUserCountTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="5dp"
                android:layout_marginBottom="20dp"
                android:gravity="center"
                android:text="10"
                android:textColor="#ffd400"
                android:textSize="10sp" />
        </FrameLayout>
        <TextView
            android:id="@+id/dateTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:layout_marginEnd="15dp"
            android:text="9/7 7:01 AM"
            android:textSize="10sp"
            app:layout_constraintEnd_toStartOf="@+id/messageProfileArea"
            app:layout_constraintTop_toBottomOf="@+id/messageContentsArea" />
        <ImageView
            android:id="@+id/messageProfileArea"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginTop="15dp"
            android:layout_marginRight="15dp"
            android:src="@drawable/profile"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <TextView
            android:id="@+id/messageNickName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="17dp"
            android:layout_marginBottom="2dp"
            android:gravity="center"
            android:text="nickname"
            android:textColor="@color/black"
            android:textSize="15sp"
            app:layout_constraintBottom_toTopOf="@+id/messageContentsArea"
            app:layout_constraintEnd_toStartOf="@+id/messageProfileArea" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

② message_recycler_view_item2.xml도 마찬가지로 수정해준다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/messageContentsArea2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:layout_marginTop="35dp"
            android:background="@drawable/your_message_box"
            android:ellipsize="end"
            android:maxWidth="230dp"
            android:padding="10dp"
            android:text="my text message"
            android:textSize="12sp"
            app:layout_constraintStart_toEndOf="@+id/messageProfileArea2"
            app:layout_constraintTop_toTopOf="parent" />
        <FrameLayout
            android:id="@+id/unreadUserCountContainer2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@+id/messageContentsArea2">
            <TextView
                android:id="@+id/unreadUserCountTextView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="5dp"
                android:layout_marginBottom="20dp"
                android:gravity="center"
                android:text="10"
                android:textColor="#ffd400"
                android:textSize="10sp" />
        </FrameLayout>
        <TextView
            android:id="@+id/dateTime2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="9/7 7:01 AM"
            android:textSize="10sp"
            android:layout_marginTop="5dp"
            android:layout_marginStart="15dp"
            app:layout_constraintStart_toEndOf="@+id/messageProfileArea2"
            app:layout_constraintTop_toBottomOf="@+id/messageContentsArea2" />
        <ImageView
            android:id="@+id/messageProfileArea2"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginTop="15dp"
            android:layout_marginLeft="15dp"
            android:src="@drawable/profile"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <TextView
            android:id="@+id/messageNickName2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="17dp"
            android:gravity="center"
            android:text="nickname"
            android:textColor="@color/black"
            android:textSize="15sp"
            app:layout_constraintBottom_toTopOf="@+id/messageContentsArea2"
            app:layout_constraintStart_toEndOf="@+id/messageProfileArea2" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

③ MessageModel에 unreadUserCount 필드를 추가한다.
var unreadUserCount : Int = 0, // 메시지를 읽지 않은 사람의 수
④ MessageAdapter를 아래와 같이 수정한다.
class MessageAdapter(private val context: Context, val items: MutableList<MessageModel>)
    : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    class ItemViewHolder1(private val view: View) : RecyclerView.ViewHolder(view) {
        val contents : TextView = view.findViewById(R.id.messageContentsArea)
        val dateTime : TextView = view.findViewById(R.id.dateTime)
        val nickName : TextView = view.findViewById(R.id.messageNickName)
        val profile : ImageView = view.findViewById(R.id.messageProfileArea)
        val unreadUserContainer : FrameLayout = view.findViewById(R.id.unreadUserCountContainer)
        val unreadUserCount : TextView = view.findViewById(R.id.unreadUserCountTextView)
    }
    class ItemViewHolder2(private val view: View) : RecyclerView.ViewHolder(view) {
        val contents : TextView = view.findViewById(R.id.messageContentsArea2)
        val dateTime : TextView = view.findViewById(R.id.dateTime2)
        val nickName : TextView = view.findViewById(R.id.messageNickName2)
        val profile : ImageView = view.findViewById(R.id.messageProfileArea2)
        val unreadUserContainer : FrameLayout = view.findViewById(R.id.unreadUserCountContainer2)
        val unreadUserCount : TextView = view.findViewById(R.id.unreadUserCountTextView2)
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val adapterLayout : View?
        return when(viewType) {
            MessageModel.VIEW_TYPE_ME -> {
                adapterLayout = LayoutInflater.from(parent.context).inflate(R.layout.message_recycler_view_item, parent, false)
                ItemViewHolder1(adapterLayout)
            }
            MessageModel.VIEW_TYPE_YOU -> {
                adapterLayout = LayoutInflater.from(parent.context).inflate(R.layout.message_recycler_view_item2, parent, false)
                ItemViewHolder2(adapterLayout)
            }
            else -> throw RuntimeException("Invalid View Type Error")
        }
    }
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = items[position]
        when (item.viewType) {
            MessageModel.VIEW_TYPE_ME -> {
                (holder as ItemViewHolder1).contents.text = item.contents
                holder.dateTime.text = item.sendTime
                holder.nickName.text = item.senderNickName
                holder.unreadUserCount.text = item.unreadUserCount.toString()
                if (item.unreadUserCount.toString().toInt() > 0) {
                    holder.unreadUserContainer!!.visibility = View.VISIBLE
                    holder.unreadUserCount.visibility = View.VISIBLE
                } else {
                    holder.unreadUserContainer!!.visibility = View.GONE
                    holder.unreadUserCount.visibility = View.GONE
                }
                if (item.senderProfileUrl != "null") {
                    Glide.with(context)
                        .load(item.senderProfileUrl)
                        .into(holder.profile)
                } else {
                    holder.profile.setImageResource(R.drawable.profile)
                }
            }
            MessageModel.VIEW_TYPE_YOU -> {
                (holder as ItemViewHolder2).contents.text = item.contents
                holder.dateTime.text = item.sendTime
                holder.nickName.text = item.senderNickName
                holder.unreadUserCount.text = item.unreadUserCount.toString()
                if (item.unreadUserCount.toString().toInt() > 0) {
                    holder.unreadUserContainer!!.visibility = View.VISIBLE
                    holder.unreadUserCount.visibility = View.VISIBLE
                } else {
                    holder.unreadUserContainer!!.visibility = View.GONE
                    holder.unreadUserCount.visibility = View.GONE
                }
                if (item.senderProfileUrl != "null") {
                    Glide.with(context)
                        .load(item.senderProfileUrl)
                        .into(holder.profile)
                } else {
                    holder.profile.setImageResource(R.drawable.profile)
                }
            }
        }
    }
    override fun getItemCount(): Int {
        return items.size
    }
    override fun getItemViewType(position: Int): Int {
        return items[position].viewType
    }
}
⑤ ChatRoomActivity를 아래와 같이 수정한다.
class ChatRoomActivity : AppCompatActivity() {
    lateinit var count : String // 채팅방 참여 인원수
    lateinit var messageAdapter : MessageAdapter
    lateinit var recyclerView : RecyclerView
    val messageList = mutableListOf<MessageModel>()
    val readerUidMap = mutableMapOf<String, Boolean>()
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_chat_room)
        readerUidMap[FirebaseAuthUtils.getUid()] = true
        val roomName = findViewById<TextView>(R.id.chatRoomName)
        val nickNameList = findViewById<TextView>(R.id.nickNameList)
        val inviteBtn = findViewById<Button>(R.id.invite)
        val userCount = findViewById<TextView>(R.id.userCount)
        // Intent로부터 데이터를 가져옴
        val chatRoomName = intent.getStringExtra("chatRoomName")
        roomName.text = chatRoomName
        val roomId = intent.getStringExtra("chatRoomId")
        val chatRoomId = roomId
        val userList = intent.getStringExtra("userList")
        nickNameList.text = userList
        CoroutineScope(Dispatchers.IO).launch {
            val response = getUserCount(chatRoomId!!)
            Log.d("userCount", response.toString())
            if (response.isSuccess) {
                count = response.result.toString()
                userCount.text = count
            } else {
                Log.d("UserListFragment", "유저의 정보를 불러오지 못함")
            }
        }
        recyclerView = findViewById<RecyclerView>(R.id.messageRV)
        messageAdapter = MessageAdapter(this, messageList)
        recyclerView.adapter = messageAdapter
        recyclerView.layoutManager = LinearLayoutManager(this)
        getMessageList(chatRoomId!!)
        Log.d("MessageList", messageList.toString())
        inviteBtn.setOnClickListener {
            val intent = Intent(this, InviteActivity::class.java)
            intent.putExtra("chatRoomId", chatRoomId)
            intent.putExtra("chatRoomName", chatRoomName)
            intent.putExtra("nickNameList", userList)
            startActivity(intent)
        }
        val participantBtn = findViewById<ImageView>(R.id.participants)
        participantBtn.setOnClickListener {
            val intent = Intent(this, ParticipantsActivity::class.java)
            intent.putExtra("chatRoomId", chatRoomId)
            startActivity(intent)
        }
        val message = findViewById<TextInputEditText>(R.id.message)
        val sendBtn = findViewById<ImageView>(R.id.send)
        lateinit var myNickName : String
        lateinit var myProfileUrl : String
        lateinit var messageModel: MessageModel
        val myUid = FirebaseAuthUtils.getUid()
        sendBtn.setOnClickListener {
            val contents = message.text.toString()
            if(contents.isEmpty()) {
                Toast.makeText(this, "메시지를 입력해주세요", Toast.LENGTH_SHORT).show()
            }
            else {
                val sendTime = getSendTime()
                CoroutineScope(Dispatchers.IO).launch {
                    val response = getUserInfo(myUid)
                    if (response.isSuccess) {
                        myNickName = response.result?.nickName.toString()
                        myProfileUrl = response.result?.imgUrl.toString()
                        val readerUids = mutableMapOf<String, Boolean>()
                        messageModel = MessageModel(myUid, myNickName, myProfileUrl, contents,
                            sendTime, readerUids, 0)
                        Log.d("readerUid", readerUids.size.toString())
                        FirebaseRef.message.child(chatRoomId!!).push().setValue(messageModel)
                    } else {
                        Log.d("ChatRoomActivity", "유저의 정보를 불러오지 못함")
                    }
                }
                message.text?.clear()
            }
        }
    }
    override fun onBackPressed() {
        readerUidMap.remove(FirebaseAuthUtils.getUid())
        val intent = Intent(this, MainActivity::class.java)
        startActivity(intent)
    }
    private suspend fun getUserCount(roomId: String) : BaseResponse<String> {
        return RetrofitInstance.chatApi.getUserCount(roomId)
    }
    private suspend fun getUserInfo(uid: String): BaseResponse<GetUserRes> {
        return RetrofitInstance.myPageApi.getUserInfo(uid)
    }
    //메시지 보낸 시각 정보 반환
    @RequiresApi(Build.VERSION_CODES.O)
    private fun getSendTime(): String {
        try {
            val localDateTime = LocalDateTime.now()
            val dateTimeFormatter = DateTimeFormatter.ofPattern("M/d  h:mm  a")
            return localDateTime.format(dateTimeFormatter)
        } catch (e: Exception) {
            e.printStackTrace()
            throw Exception("시간 정보를 불러오지 못함")
        }
    }
    private fun getMessageList(chatRoomId: String) {
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {
                messageList.clear()
                val newMessages = mutableListOf<MessageModel>() // 새로운 메시지를 저장할 리스트 생성
                for (dataModel in dataSnapshot.children) {
                    val messageModel = dataModel.getValue(MessageModel::class.java)
                    val messageId = dataModel.key
                    if (messageModel != null) {
                        if (messageId != null) {
                            // readerUidMap을 업데이트
                            FirebaseRef.message.child(chatRoomId!!).child(messageId).child("readerUids")
                                .updateChildren(readerUidMap as Map<String, Boolean>)
                                .addOnCompleteListener { readerUidTask ->
                                    if (readerUidTask.isSuccessful) {
                                        // readerUid 업데이트가 성공한 경우 unreadUserCount를 계산하여 업데이트합니다.
                                        val unreadUserCount = count.toInt() - messageModel.readerUids.size
                                        FirebaseRef.message.child(chatRoomId!!).child(messageId).child("unreadUserCount")
                                            .setValue(unreadUserCount)
                                    } else {
                                        Log.d("ChatRoomActivity", "reader UID를 업데이트하지 못함")
                                    }
                                }
                        }
                        if (messageModel.senderUid != FirebaseAuthUtils.getUid()) {
                            messageModel.viewType = MessageModel.VIEW_TYPE_YOU
                        }
                        newMessages.add(messageModel)
                    }
                }
                messageList.addAll(newMessages)
                messageAdapter.notifyDataSetChanged()
                Log.d("MessageList", messageList.toString())
                recyclerView.post {
                    recyclerView.scrollToPosition(recyclerView.adapter?.itemCount?.minus(1) ?: 0)
                }
            }
            override fun onCancelled(databaseError: DatabaseError) {
                Log.w("MyMessage", "onCancelled", databaseError.toException())
            }
        }
        FirebaseRef.message.child(chatRoomId).addValueEventListener(postListener)
    }
}
이제 코드를 실행해보면, 아래와 같이 읽지 않은 유저의 수가 메시지 옆에 표시될 것이다.
