Skip to main content
Version: 2.x.x

PubSub - Android

PubSub is a short acronym for Publish-Subscribe mechanism. This mechanism is used to send and recieve messages from a particular topic. As the name suggests, for someone to send a message, they have to specify the topic and the message which should be published and for someone to receive a message, they should be subscribed to that topic.

Here is a visual to better understand publish-subscribe mechanism.

pubsub

pubSub

In order to use PubSub in meeting, VideoSDK provides a class pubSub which allows you to subscribe to any topic and publish to any topic allowing to pass on messages and instructions during the meeting easily.

publish()

  • This method is used for publishing message of specific topic.
  • This method can be accessed from the pubSub class, which is subclass of Meeting class.
  • This method will accept following parameters as input:
    • topic: This will be the topic for which you are publishing a message.
    • message: This will be the actual message to be published. It has to be in String format.
    • options: This is an object of PubSubPublishOptions which specifies the options for publish. PubSubPublishOptions has 2 properties.
      • persist : persist offered the option of keeping the message around for the duration of the session. When persist is set to true, that message will be retained for upcoming participants and will be available in VideoSDK Session Dashboard with .CSV format after completion of session.
      • sendOnly: If you want to send a message to specific participants, you can pass their respective participantId in form of String[]. If you don't provide any IDs or pass a null value, the message will be sent to all participants by default. This is optional parameter.
    • payload: If you need to include additional information along with a message, you can pass here as JSONObject. This is optional parameter.
private fun sendMessage() {
// publish message
val options = PubSubPublishOptions()
options.isPersist = true
try {
meeting!!.pubSub.publish("CHAT", "Hello Everyone!", options)
} catch (e: Exception) {
// Meeting is not connected yet, or is reconnecting
Log.d("VideoSDK", "publish failed: ${e.message}")
}
}

subscribe()

  • This method is used to subscribe for particular topic.

  • This method will accept following parameters as input:

    • topic: This will be the topic to be subscribed.

    • listener: This is an object of PubSubMessageListener containing the following callbacks:

      • onMessageReceived(message) — Called for every realtime message as soon as it is received.

        • Use this when: You want to handle each message individually, such as appending it to a chat, triggering a notification, or updating message-specific state.
        • Don't use this when: The topic is high-throughput / large-scale (busy chats, live reactions, cursor positions). Firing once per message causes excessive UI updates — use onBatchReceived() instead.
      • onBatchReceived(messages) — Called once per live batch with all messages of that batch. These are the same messages delivered through onMessageReceived(), only grouped — use one path or the other, not both.

        • Use this when: Handling messages in bulk is cheaper, such as one UI update or one database transaction per batch instead of one per message.
        • Note: Batched delivery is enabled per meeting by the server configuration, not by subscribe options. Where it is not enabled this callback never fires and live messages arrive solely through onMessageReceived(), so handle both paths.
      • onOldMessagesReceived(messages) — Called with the topic's persisted history in batches, once per batch with a partial list. Only messages published with persist enabled are delivered here. Append each batch to what you already hold rather than replacing it. A topic with no persisted history never fires this callback.

        • Use this when: Loading chat history or restoring previously sent messages when a participant joins the meeting.
      • onOldMessagesReceived(messages, info) — The same history replay, plus batch metadata: info.isLast() is true on the final batch.

        • Use this when: You need to know that history replay is complete — for example, to hide a loader once the full history is rendered.
      • onMessageDrop(info) — Called when incoming realtime messages cannot be delivered. This can happen:

        • because the client cannot keep up with the incoming message rate (for example, due to a slow network or high CPU usage), causing overflow, or
        • because newMessageLimit is configured, which intentionally limits how many realtime messages are delivered every 500 ms. Any messages exceeding the configured limit within that window are discarded.

        info.getDroppedCount() contains the number of messages that were not delivered.

        • Use this when: Notifying users that some realtime messages were missed, monitoring the effects of newMessageLimit, or logging dropped messages for debugging and observability.
    • options: This is an object of PubSubSubscribeOptions which specifies the options for subscribe. This is optional parameter. PubSubSubscribeOptions has 4 properties.

      • oldMessageLimit: This limits how many persisted messages are fetched when you subscribe. Pass null for all history, 0 for none, or N for the last N messages. Defaults to null.
      • realtimeOverflow: This decides what happens when live messages arrive faster than they can be delivered. QUEUE buffers them and delivers them paced, dropping the oldest on overflow; DROP keeps only the newest messages of each delivery window. Defaults to QUEUE.
      • maxQueue: This is the buffer ceiling for live messages under QUEUE. It is only valid with QUEUE, and combining it with DROP will throw an IllegalArgumentException. If you don't provide any value, the server decides.
      • newMessageLimit: This caps how many new messages this subscriber accepts per server batching window (500 ms). If you don't provide any value, it is unlimited.

The object of PubSubMessage contains following properties:

  • id: This is the unique id of the message. Type String.
  • message: This will be the actual message that was sent. Type String.
  • senderId: This represents the participantId of the participant who sent the message. Type String.
  • senderName: This represents the displayName of the participant who sent the message. Type String.
  • timestamp: This will be the timestamp for when the message was published. Type long.
  • topic: This will be the name of the topic the message was published to. Type String.
  • payload: This will be the data that you have sent along with the message. Type JSONObject.
val pubSubMessageListener = object : PubSubMessageListener {
override fun onMessageReceived(message: PubSubMessage) {
Log.d("#message", "onMessageReceived: ${message.message}")
}

override fun onOldMessagesReceived(messages: List<PubSubMessage>) {
Log.d("#message", "onOldMessagesReceived: $messages")
}

override fun onOldMessagesReceived(messages: List<PubSubMessage>, info: PubSubHistoryInfo) {
Log.d("#message", "onOldMessagesReceived: ${messages.size} messages, isLast: ${info.isLast}")
}

override fun onBatchReceived(messages: List<PubSubMessage>) {
Log.d("#message", "onBatchReceived: ${messages.size} messages")
}

override fun onMessageDrop(info: PubSubMessageDropInfo) {
Log.d("#message", "onMessageDrop: dropped ${info.droppedCount} messages")
}
}

override fun onCreate(savedInstanceState: Bundle?) {
//...

// Subscribe for 'CHAT' topic
try {
meeting!!.pubSub.subscribe("CHAT", pubSubMessageListener)
} catch (e: Exception) {
// Meeting is not connected yet, or is reconnecting
Log.d("VideoSDK", "subscribe failed: ${e.message}")
}
}

unsubscribe()

  • This method is used to unsubscribe for particular topic.

  • This method will accept two parameters as input:

    • topic: This will be the topic to be unsubscribed.
    • listener: This is an object of PubSubMessageListener, which was passed in subscribe().
fun unsubscribe() {
// Unsubscribe 'CHAT' topic
try {
meeting!!.pubSub.unsubscribe("CHAT", pubSubMessageListener)
} catch (e: Exception) {
// Meeting already ended or is reconnecting — nothing left to unsubscribe from
Log.d("VideoSDK", "unsubscribe skipped: ${e.message}")
}
}
caution

All three methods require a joined meeting and throw if it is not connected. See Errors for what each method throws and how server-side failures are reported.

Errors

PubSub reports failures through method exceptions (try / catch) or through MeetingEventListener.onError(JSONObject).

publish() throws:

  • IllegalStateException"You must join the meeting before using PubSub." The meeting has not reached CONNECTED (or has already left). Also fires onError with code 3001.
  • IllegalStateException"The meeting is reconnecting. Please try again once it reconnects." No error event is fired, because your app tracks state via onMeetingStateChanged.
  • IllegalStateException"Operation Timeout." The PubSub connection is disconnected or closed, so the operation cannot proceed. Also fires onError with code 3013.

subscribe() throws:

  • IllegalArgumentException"You already subscribed to this topic with same listener." One listener instance may hold at most one subscription per topic. Call unsubscribe() before re-subscribing, or create a second listener instance.
  • IllegalArgumentExceptionoldMessageLimit is negative. It must be null (all history) or >= 0.
  • IllegalArgumentExceptionmaxQueue is less than 1.
  • IllegalArgumentExceptionmaxQueue was set while realtimeOverflow is DROP. It is only valid with QUEUE.
  • IllegalArgumentExceptionnewMessageLimit is negative. It must be null or >= 0.
  • IllegalStateException"You must join the meeting before using PubSub." The meeting has not reached CONNECTED (or has already left). Also fires onError with code 3001.
  • IllegalStateException"The meeting is reconnecting. Please try again once it reconnects." No error event is fired, because your app tracks state via onMeetingStateChanged.
  • IllegalStateException"Operation Timeout." The PubSub connection is disconnected or closed, so the operation cannot proceed. Also fires onError with code 3013.

Options are validated before initiating network operations, so an invalid configuration fails immediately.

unsubscribe() throws:

  • IllegalStateException"You must join the meeting before using PubSub." The meeting has not reached CONNECTED (or has already left). Also fires onError with code 3001.
  • IllegalStateException"The meeting is reconnecting. Please try again once it reconnects." No error event is fired, because your app tracks state via onMeetingStateChanged.
  • IllegalStateException"Operation Timeout." The PubSub connection is disconnected or closed, so the operation cannot proceed. Also fires onError with code 3013.

Reported through onError:

CodeNameDescription
3001ERROR_ACTION_PERFORMED_BEFORE_MEETING_JOINEDA PubSub method was called before the meeting was joined.
3012ERROR_GET_SERVER_CONFIG_FAILEDUnable to fetch server configuration during meeting join.
3013OPERATION_TIMEOUTPubSub operation timed out due to a disconnected or closed connection.
4087PUBSUB_PUBLISH_FAILEDMessage could not be delivered — server rejected it or connection dropped before acknowledgment.
4088PUBSUB_SUBSCRIBE_FAILEDServer rejected the subscription. The listener is unregistered again.
4089PUBSUB_UNSUBSCRIBE_FAILEDServer rejected the unsubscribe request. The listener is removed locally either way.

Applications of PubSub

PubSub is a very powerful mechanism which can be used to do a lot of things which can make your meeting experience much more interactive. Some of the most common use cases that we have come across for PubSub during a meeting are listed below:

  1. Chat: You can utilise this to develop various Chat features, such as Private Chat and Group Chat. You can follow our chat integration guide here.
  2. Raise Hand: You can allow attendees to raise their hands at any time during the meeting, informing everyone else that someone has done so.
  3. Layout Switching: You can change the meeting's layout for every participant at once during the meeting, such as from Grid layout to Spotlight or from Grid Layout to Sidebar.
  4. Poll: You may make polls, let users respond to them, and display the results at the end of a poll.
  5. Question Answer Session: You can also design interactive functionality that is question-and-answer based.

Downloading PubSub Messages

All the messages from PubSub published with persist : true can be downloaded as a .csv file. This file will be available in the VideoSDK dashboard as well as through the Sessions API.

API Reference

The API references for all the methods and events utilised in this guide are provided below.

Got a Question? Ask us on discord