AI Integration Quick Reference
AI Integration Quick Reference
Thread subscription builds on Threaded Messages. A thread is identified by the ID of its parent message — there is no separate thread ID.
How State Works
The SDK keeps no subscription state of its own. There is no cache and no thread listener to reconcile:- Every message fetch asks the server for the flag, and it arrives on the message — read it with
BaseMessage.isThreadSubscribed(). subscribeToThread()andunsubscribeFromThread()call back when the server has accepted the change. The callback is the acknowledgement — there is no follow-up event.
Subscribe to a Thread
To subscribe to a thread, use thesubscribeToThread method with the ID of the thread’s parent message. The call is idempotent — subscribing to a thread the user is already subscribed to succeeds silently. Subscribing to a message with zero replies is allowed; the user will be notified when the first reply arrives.
- Java
- Kotlin
Unsubscribe from a Thread
To unsubscribe from a thread, use theunsubscribeFromThread method. This too is idempotent — unsubscribing from a thread the user is not subscribed to succeeds silently.
- Java
- Kotlin
Read the Subscription State
The subscription state rides on the message. Read it withisThreadSubscribed() on the thread’s parent message.
- Java
- Kotlin
MessagesRequestBuilder that opt-in is withThreadSubscribed(boolean), and it defaults to true — leave it there. Passing false trades the signal away for a marginally smaller response, and isThreadSubscribed() then reads false for every message, indistinguishable from a genuine unsubscribe.
A message delivered over the websocket carries no flag and therefore reads
false. That is not a claim that the user is unsubscribed — it means nobody asked. When you need certainty for a thread you have not fetched (a deep link, for instance), fetch the parent message with CometChat.getMessageDetails() and read the flag off the result.You are subscribed to your own messages
Sending a message subscribes you to the thread it may later grow — there is nothing to call. The message comes back with the flag set, both in the send response and on later fetches, and only for you: the flag is per-viewer, so the same message readsfalse for everybody else until they subscribe themselves.
That default is what makes the flag meaningful on your own messages. Since it starts out true, a false on a message you sent — read from a fetch, not the socket — is not silence. It means you unsubscribed, and nothing should quietly put you back.
This only holds for a message you sent and obtained from a fetch. On anyone else’s message, or on anything socket-delivered, false still just means the server was not asked.
Keeping your own copies in sync
The same thread can be represented by several message objects at once — a row in the message list, the parent of an open thread view, an entry in a thread inbox. Because the SDK caches nothing, usesetThreadSubscribed() to align the copies you hold once you know the answer:
- Java
- Kotlin
Reacting to Replies
A thread reply is an ordinary message with a parent message ID set, delivered through the standardMessageListener like any other message. There is no separate thread listener.
- Java
- Kotlin
CometChat.removeMessageListener(listenerID).
Using MessageListener also gets you onMessageEdited and onMessageDeleted for replies, which a thread-only channel would not. Your own replies do not arrive on a listener — bump your thread row from the sendMessage() callback instead.
Fetch the Threads a User Participates In
To build a thread inbox — one row per thread the user is part of — create aThreadsRequest using the ThreadsRequestBuilder. The list is the union of threads the user started, replied in, was mentioned in, or explicitly subscribed to. Every returned row is, by definition, a thread the user is subscribed to: participation is subscription, and unsubscribing removes the row.
- Java
- Kotlin
fetchNext() repeatedly to page forward; hasMore() tells you whether more pages exist. A ThreadsRequest is forward-only — there is no fetchPrevious(). To refresh the list from the top, build a new request from the builder and replace your list with its results. Calling fetchNext() while a fetch is already in flight fails with a request-in-progress error, and a setLimit() outside 1…1000 fails at fetch time rather than at build().
The MessageThread Model
Each row is aMessageThread — enough to render an inbox without fetching the parent message separately.
getUnreadReplyCount() returns null, not 0, when the count is unknown. Treat null as “no badge” rather than as zero unread.The list starts empty for every user when the feature launches — it fills up as users reply, get mentioned, and subscribe to threads. There is no historical backfill.
Notification Preferences
The notification preference for replies gains a new value so users can be notified only for threads they are subscribed to:SUBSCRIBE_TO_SUBSCRIBED_THREADS in the RepliesOptions enum.
See Notification Preferences for how to read and update a user’s preferences.
Error Handling
Next Steps
Threaded Messages
Send and fetch replies inside a thread
Mentions
@-mentions, which auto-subscribe a user to a thread
All Real Time Listeners
Every listener the SDK exposes, in one place
Save A Message
Bookmark a message privately, across conversations