Skip to main content

Send messages

This guide covers how to send messages in direct channels, group channels, and open channels using the Nexconn SDK.

tip

By default, users who have not joined an open channel can still send messages to it. To restrict this, go to the Nexconn Console, navigate to Chat > Chat settings > Open Channels, and enable Restrict messaging to joined participants. This setting does not affect server-side APIs.

Message content types

The Message object's content property holds either a standard message content (MessageContent subclass) or a media message content (MediaMessageContent subclass).

FeatureContent typeBase classDescription
Text messageTextMessageMessageContentPlain text content.
Quote replyReferenceMessageMediaMessageContentQuoted message content for reply functionality.
Image messageImageMessageMediaMessageContentImage content with original image support.
GIF messageGIFMessageMediaMessageContentAnimated GIF content.
File messageFileMessageMediaMessageContentFile attachment content.
Voice messageHDVoiceMessageMediaMessageContentHigh-quality voice recording content.
Mention (@)N/AN/ANot a predefined type. See Send a mention message.

These are some of the built-in message content types. You can also create custom content types and send them with channel.sendMessage(). See Custom message types.

Important
  • Channel-based architecture: Obtain a channel object (e.g., GroupChannel, DirectChannel) before sending messages.
  • Unified API: Use channel.sendMessage() for all message types, including media messages.
  • Rate limit: The client SDK limits sending to 5 messages per second.

Get a channel object

Before sending a message, obtain the target channel object using the type-specific factory method:

kotlin
// Use the type-specific factory method (recommended)
val groupChannel = GroupChannel(groupId)
val directChannel = DirectChannel(userId)
val openChannel = OpenChannel(openChannelId)

Send a text message

Text messages are the most common message type. The following example sends a text message to a group channel.

kotlin
// 1. Get the channel object
val groupChannel = GroupChannel(groupId)

// 2. Configure send parameters (message content + optional push config)
val params = SendMessageParams(TextMessage("Hello, World!")).apply {
pushConfig = PushConfig().apply {
pushContent = "You received a new message"
pushData = """{"key":"value"}"""
}
}

// 3. Send the message
groupChannel.sendMessage(params, object : SendMessageHandler {
override fun onAttached(message: Message) {
// Message saved to local database — update the UI
Log.d("SendMessage", "Saved to DB, messageId: ${message.messageId}")
updateMessageUI(message)
}

override fun onResult(message: Message, error: NCError?) {
if (error == null) {
Log.d("SendMessage", "Message sent successfully")
markMessageAsSent(message)
} else {
Log.e("SendMessage", "Send failed: ${error.message}")
handleSendError(message, error)
}
}
})

Sending to different channel types

kotlin
// Direct channel
val directChannel = DirectChannel(userId)
directChannel.sendMessage(params, handler)

// Group channel
val groupChannel = GroupChannel(groupId)
groupChannel.sendMessage(params, handler)

// Open channel
val openChannel = OpenChannel(chatRoomId)
openChannel.sendMessage(params, handler)

// Community channel
val communityChannel = CommunityChannel(communityId)
communityChannel.sendMessage(params, handler)

Send an image message

Image messages support both original and compressed images. The SDK handles compression and thumbnail generation automatically.

kotlin
// 1. Get the channel object
val channel = DirectChannel(userId)

// 2. Configure send parameters (image content + optional push config)
val params = SendMediaMessageParams(
ImageMessage().apply {
localPath = "file:///path/to/image.jpg"
original = true // true: send original, false: send compressed
}
).apply {
pushConfig = PushConfig().apply {
pushContent = "You received an image"
}
}

// 3. Send the media message
channel.sendMediaMessage(params, object : SendMediaMessageHandler {
override fun onAttached(message: Message) {
updateMessageUI(message)
}

override fun onProgress(message: Message, progress: Int) {
Log.d("Upload", "Upload progress: $progress%")
updateUploadProgress(message, progress)
}

override fun onResult(message: Message, error: NCError?) {
if (error == null) {
Log.d("SendMedia", "Image sent successfully")
markMessageAsSent(message)
} else {
Log.e("SendMedia", "Image send failed: ${error.message}")
handleSendError(message, error)
}
}

override fun onCanceled(message: Message) {
Log.d("SendMedia", "Image send canceled")
}
})

Image compression

The SDK handles image compression automatically:

  • Thumbnail: Generated at 30% quality, longest side capped at 240 px.
  • Compressed: If original is not set, the image is compressed at 85% quality, longest side capped at 1080 px.
  • Original: If original = true, no compression is applied.

Modifying the default compression settings is generally not recommended.

Send a file message

File messages support any file type.

kotlin
val params = SendMediaMessageParams(
FileMessage().apply {
localPath = "file:///path/to/document.pdf"
name = "document.pdf"
size = fileSize
}
).apply {
pushConfig = PushConfig().apply {
pushContent = "You received a file"
}
}

channel.sendMediaMessage(params, object : SendMediaMessageHandler {
override fun onAttached(message: Message) { updateMessageUI(message) }
override fun onProgress(message: Message, progress: Int) { updateUploadProgress(message, progress) }
override fun onResult(message: Message, error: NCError?) { if (error == null) markMessageAsSent(message) else handleSendError(message, error) }
override fun onCanceled(message: Message) { }
})

File size limits

  • GIF files: 2 MB max
  • Other files: 100 MB max

Send a voice message

Voice messages carry audio recordings.

kotlin
val params = SendMediaMessageParams(
HDVoiceMessage().apply {
localPath = "file:///path/to/audio.amr"
duration = audioDuration
}
)
channel.sendMediaMessage(params, object : SendMediaMessageHandler {
override fun onAttached(message: Message) { }
override fun onProgress(message: Message, progress: Int) { }
override fun onResult(message: Message, error: NCError?) { if (error == null) markMessageAsSent(message) else handleSendError(message, error) }
override fun onCanceled(message: Message) { }
})

Upload media to your own server

You can send files hosted on your own server. Pass the remote URL when constructing the media message content. In this case, the file is not uploaded to Nexconn servers, and there is no file size limit. Use the sendMessage method directly.

If you want the SDK to send the message only after you upload the file, upload the file yourself and then use sendMessage with the remote URL directly:

kotlin
// 1. Upload your file to your server first
val remoteUrl = uploadToMyServer(localFilePath)

// 2. Create the message content with the remote URL
val imageContent = ImageMessage().apply {
this.remoteUrl = remoteUrl
}

// 3. Send the message using sendMessage (not sendMediaMessage)
val params = SendMessageParams(imageContent)
channel.sendMessage(params, object : SendMessageHandler {
override fun onAttached(message: Message) {}
override fun onResult(message: Message, error: NCError?) {}
})

Send a mention message

Mentions (@) are not a predefined message type (see Message type overview). Instead, Nexconn embeds mentionedInfo data within messages to enable mention functionality.

The [MentionedInfo] field in MessageContent stores information about mentioned users. Both built-in and custom message types inherit [MessageContent], so they all support mentions.

Nexconn supports adding mentionedInfo when sending messages to group channels and community channels. Construct a MentionedInfo object and set it on the MessageContent before sending.

Java
List<String> userIdList = new ArrayList<>();
userIdList.add("userId1");
userIdList.add("userId2");
MentionedInfo mentionedInfo = new MentionedInfo(MentionedType.USER, userIdList, null);
TextMessage messageContent = new TextMessage("Hello team");
messageContent.setMentionedInfo(mentionedInfo);

MentionedInfo parameters

ParameterTypeDescription
typeMentionedTypeRequired. MentionedType.ALL mentions everyone. MentionedType.USER mentions specific users listed in userIdList.
userIdListList<String>The list of mentioned user IDs. Required when type is USER. Also supported when type is ALL to additionally highlight specific users.
mentionedContentStringThe push notification content shown when a mention triggers an offline push. If null, a default message like "Someone mentioned you" is displayed. This overrides all other pushContent settings.

The following example sends a text message mentioning specific users in a group channel:

kotlin
val params = SendMessageParams(
TextMessage("Hello team").apply {
mentionedInfo = MentionedInfo(
type = MentionedType.USER,
userIdList = listOf("userId1", "userId2"),
mentionedContent = null
)
}
)

GroupChannel("groupId").sendMessage(params, object : SendMessageHandler {
override fun onAttached(message: Message) {}
override fun onResult(message: Message, error: NCError?) {}
})

After receiving a message, extract the MentionedInfo to handle mentions in your UI:

kotlin
val mentionedInfo = message.content?.mentionedInfo

Push notifications

tip

Open channels do not support missed messages or push notifications.

If your app has third-party push services configured in Nexconn, the server sends push notifications when the recipient is offline, based on the message type, supported push channels, and the recipient's Do Not Disturb settings.

Push notifications appear in the system notification bar. Built-in message types display default notification titles and content. For details, see User content message formats.

To customize push notification titles, content, and other attributes, use PushConfig via SendMessageParams.pushConfig or SendMediaMessageParams.pushConfig.

Configure message push properties

Set a PushConfig on SendMessageParams.pushConfig (or SendMediaMessageParams.pushConfig) to customize its push behavior:

  • Custom push title and content
  • Additional push data
  • Force display of notification content regardless of recipient settings
  • Push template ID
kotlin
val pushConfig = PushConfig().apply {
pushTitle = title
pushContent = content
pushData = data
forceShowDetailContent = forceDetail
templateId = ""
}
val params = SendMessageParams(textMessage).apply {
this.pushConfig = pushConfig
}

Push notifications for custom messages

Built-in message types have default push notification content (see User content message formats). For custom message types, you must provide a pushContent field; otherwise, offline push notifications will not be sent.

  • If a custom message type needs push support, provide pushContent in PushConfig via the send parameters (SendMessageParams.pushConfig).
  • If a custom message type does not need push support (e.g., it serves as a business-layer command), leave pushContent empty.
tip

To enable push notifications for custom messages, always provide pushContent. Without it, the recipient will not receive offline push notifications.

Disable push for a message

By default, the server triggers push notifications when a recipient is offline. To suppress push for a specific message, set disableNotification to true in SendMessageParams or SendMediaMessageParams.

kotlin
val params = SendMessageParams(TextMessage("Message content")).apply {
disableNotification = true
}
DirectChannel("targetId").sendMessage(params, handler)

When the recipient comes back online, missed messages (cached for up to 7 days) are automatically delivered for direct, group, and system channels. Community channel messages do not support the missed message mechanism and must be fetched manually.

Pass custom data

To transmit custom data to the other party:

  • MessageContent extra field: Set via MessageContent.extra. This field is sent with the message to the other party. Do not confuse with Message.extra, which is local-only.
  • Push data (pushData): Set via PushConfig.pushData in the send parameters. Push data is only delivered when a push notification is triggered. Retrieve it on the receiving end from the push notification payload.

Handle send failures

For stored message types (see Message type overview), if the onAttached callback fires, the message has been saved to the local database and is in the message list.

  • If saving fails, check whether the parameters are valid and whether local storage is writable.
  • If saving succeeds but sending fails (onResult with a non-null error), display the failed message in the UI and cache the Message instance from onResult. Resend later by passing the same instance to sendMessage/sendMediaMessage. Creating a new message with the same content results in a duplicate entry in the local message list.

For non-stored message types, cache and retry the message instance, or create a new one.

Forward and broadcast messages

Forward messages: The Chat SDK does not provide a dedicated forwarding API. Use the standard send message API to forward message content.

Broadcast messages: To send a message to multiple users (or multiple target IDs), consider:

  • Loop through the client send message API. Note the rate limit of 5 messages per second.
  • Use the server-side IM API from your backend. The Send direct message API supports sending to multiple users in a single call. You can also use Send group message and Send open channel message to send to multiple groups or open channels.