Documentation Index Fetch the complete documentation index at: https://cometchat-22654f5b-docs-android-v6-beta2.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
AI Integration Quick Reference
Field Value Packages com.cometchat:chatuikit-kotlin · com.cometchat:chatuikit-jetpackKey components CometChatThreadHeader, CometChatMessageList, CometChatMessageComposerPurpose Implement threaded replies so users can respond to specific messages in a focused sub-conversation. Related Threaded Messages Header , Message List , Message Composer , All Guides
Implement threaded replies in your Android chat app using CometChat’s UI Kit, enabling users to reply to specific messages in a focused sub-conversation.
Overview
Threaded replies allow users to respond directly to a specific message in one-on-one or group chats, improving context and readability:
Organizes related replies into a dedicated thread view.
Mirrors functionality in Slack, Discord, and WhatsApp.
Maintains clarity in active conversations.
Users tap a message → open thread screen → view parent message + replies → compose within thread.
Prerequisites
Android project in Android Studio.
CometChat Android UI Kit v5 (com.cometchat:chatuikit-kotlin or com.cometchat:chatuikit-jetpack) added to your build.gradle.
Valid CometChat App ID , Auth Key , and Region initialized.
<uses-permission android:name="android.permission.INTERNET"/> in AndroidManifest.xml.
Logged-in user via CometChatUIKit.login().
Existing MessagesActivity using CometChatMessageList.
Components
Component Role activity_thread_message.xmlDefines thread UI: header, message list, composer, unblock. ThreadMessageActivityHosts thread screen; initializes UI & ViewModel. ThreadMessageViewModelFetches parent message & thread replies; manages state. CometChatMessageListDisplays threaded replies when given parent message ID. CometChatMessageComposerComposes and sends replies with parentMessageId. CometChatThreadHeaderDisplays the parent message context at the top of the thread.
Integration Steps
Step 1: Add Thread Layout
Create res/layout/activity_thread_message.xml:
activity_thread_message.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:orientation = "vertical" >
< com.cometchat.uikit.kotlin.presentation.threadheader.ui.CometChatThreadHeader
android:id = "@+id/threadHeader"
android:layout_width = "match_parent"
android:layout_height = "wrap_content" />
< com.cometchat.uikit.kotlin.presentation.messagelist.ui.CometChatMessageList
android:id = "@+id/threadMessageList"
android:layout_width = "match_parent"
android:layout_height = "0dp"
android:layout_weight = "1" />
< LinearLayout
android:id = "@+id/unblockLayout"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:gravity = "center"
android:padding = "12dp"
android:visibility = "gone" >
< Button
android:id = "@+id/unblockBtn"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Unblock" />
</ LinearLayout >
< com.cometchat.uikit.kotlin.presentation.messagecomposer.ui.CometChatMessageComposer
android:id = "@+id/threadComposer"
android:layout_width = "match_parent"
android:layout_height = "wrap_content" />
</ LinearLayout >
Step 2: Set up ThreadMessageActivity
Initialize UI & handle blocked-user flows:
Kotlin (XML Views)
Jetpack Compose
import com.cometchat.uikit.kotlin.presentation.threadheader.ui.CometChatThreadHeader
import com.cometchat.uikit.kotlin.presentation.messagelist.ui.CometChatMessageList
import com.cometchat.uikit.kotlin.presentation.messagecomposer.ui.CometChatMessageComposer
class ThreadMessageActivity : AppCompatActivity () {
override fun onCreate (savedInstanceState: Bundle ?) {
super . onCreate (savedInstanceState)
setContentView (R.layout.activity_thread_message)
val header = findViewById < CometChatThreadHeader >(R.id.threadHeader)
val messageList = findViewById < CometChatMessageList >(R.id.threadMessageList)
val composer = findViewById < CometChatMessageComposer >(R.id.threadComposer)
val unblock = findViewById < View >(R.id.unblockLayout)
val rawMessage = intent. getStringExtra ( "raw_json" )
val viewModel = ViewModelProvider ( this )[ThreadMessageViewModel:: class .java]
if (rawMessage != null ) {
val parentMessage = BaseMessage. processMessage ( JSONObject (rawMessage))
viewModel. setParentMessage (parentMessage)
}
lifecycleScope. launch {
viewModel.parentMessage. collect { msg ->
msg?. let {
header. setParentMessage (it)
messageList. setParentMessage (it.id)
composer. setParentMessageId (it.id)
}
}
}
// Handle blocked user
if (isBlockedByMe) {
composer.visibility = View.GONE
unblock.visibility = View.VISIBLE
}
}
}
import com.cometchat.uikit.compose.presentation.threadheader.ui.CometChatThreadHeader
import com.cometchat.uikit.compose.presentation.messagelist.ui.CometChatMessageList
import com.cometchat.uikit.compose.presentation.messagecomposer.ui.CometChatMessageComposer
@Composable
fun ThreadMessageScreen (rawJson: String , isBlockedByMe: Boolean = false ) {
val parentMessage = remember {
BaseMessage. processMessage ( JSONObject (rawJson))
}
Column (modifier = Modifier. fillMaxSize ()) {
CometChatThreadHeader (parentMessage = parentMessage)
CometChatMessageList (
parentMessageId = parentMessage.id,
modifier = Modifier. weight ( 1f )
)
if (isBlockedByMe) {
UnblockPrompt (onUnblock = { /* unblock logic */ })
} else {
CometChatMessageComposer (parentMessageId = parentMessage.id)
}
}
}
Step 3: Create ThreadMessageViewModel
Store parent message and expose via StateFlow:
class ThreadMessageViewModel : ViewModel () {
private val _parentMessage = MutableStateFlow < BaseMessage ?>( null )
val parentMessage: StateFlow < BaseMessage ?> = _parentMessage. asStateFlow ()
var id: Long = 0
private set
fun setParentMessage (message: BaseMessage ?) {
if (message != null ) {
id = message.id
_parentMessage. value = message
}
}
}
Step 4: Hook Thread Entry from Message List
In your MessagesActivity, capture thread icon taps:
Kotlin (XML Views)
Jetpack Compose
messageList. setOnThreadRepliesClick { context, baseMessage, template ->
val intent = Intent (context, ThreadMessageActivity:: class .java)
intent. putExtra ( "raw_json" , baseMessage.rawMessage. toString ())
intent. putExtra ( "reply_count" , baseMessage.replyCount)
context. startActivity (intent)
}
CometChatMessageList (
user = user,
onThreadRepliesClick = { baseMessage, template ->
navController. navigate ( "thread/ ${ baseMessage.rawMessage } " )
},
modifier = Modifier. weight ( 1f )
)
Implementation Flow
User taps thread icon on a message.
Intent launches ThreadMessageActivity with raw message JSON (or Compose navigation).
ViewModel stores parent message and exposes via StateFlow.
Header & MessageList render parent + replies.
Composer sends new replies under the parent message.
Live updates flow automatically via UI Kit.
Customization Options
Styling: Override theme attributes or call setter methods on views.
Header Height: threadHeader.setMaxHeight(...).
Hide Reactions: threadHeader.setReactionVisibility(View.GONE).
Filtering & Edge Cases
Group Membership: Verify membership before enabling composer.
Empty Thread: Show placeholder if no replies.
Blocked Users: Composer hidden; use unblock layout.
Blocked-User Handling
Kotlin (XML Views)
Jetpack Compose
if (user.isBlockedByMe) {
composer.visibility = View.GONE
unblockLayout.visibility = View.VISIBLE
}
if (user.isBlockedByMe) {
UnblockPrompt (onUnblock = { /* unblock logic */ })
} else {
CometChatMessageComposer (parentMessageId = parentMessage.id)
}
Group vs. User-Level Differences
Scenario Behavior ReceiverType.USERDirect replies allowed if not blocked. ReceiverType.GROUPChecks membership before thread access. Blocked User Composer hidden; unblock layout shown. Not in Group Show option to join group first.
Summary / Feature Matrix
Feature Component / Method Show thread option setOnThreadRepliesClick()Display thread messages messageList.setParentMessage(parentMessage.getId())Show parent message header.setParentMessage(parentMessage)Compose reply composer.setParentMessageId(parentMessage.getId())Handle blocked users isBlockedByMe(), hide composer + show unblock UI
Next Steps & Further Reading
Android Sample App (Kotlin) Explore this feature in the CometChat SampleApp:
GitHub → SampleApp