In-Session Communication

This page covers all APIs for communicating inside an EnableX Android video session: text chat (including edit and delete), custom data signalling, file sharing, screen sharing, canvas streaming, annotation, and live transcription.

Chat

EnableX supports public (broadcast), private (one-to-one), and group chat messaging. Messaging does not require the sender to have a published stream or the receiver to have a subscribed stream.

Send a Chat Message

EnxRoom.sendMessage() sends a text message to one or more participants in the session.

ParameterTypeDescription
messageStringThe text message to send.
isBroadcastBooleantrue to send to all participants (public); false to send to specific recipients (private/group).
recipientIDsArrayList of client IDs to receive the message. Applicable only when isBroadcast is false.
CallbackDelivered ToDescription
onACKSendMessageSenderAcknowledgment that the message was sent, including a unique messageId.
onMessageReceivedRecipientsDelivers the received message as a JSONObject.
room?.sendMessage("Hello everyone!", "public", JSONArray())

val targets = JSONArray().put(targetClientId)
room?.sendMessage("Private note", "private", targets)

override fun onACKSendMessage(jsonObject: JSONObject?) {
    // Your message was sent successfully
}

override fun onMessageReceived(jsonObject: JSONObject?) {
    val message = jsonObject?.optString("message")
    val from = jsonObject?.optString("from")
    val type = jsonObject?.optString("type") // public | private
}

Edit a Chat Message

EnxRoom.transactMessage() edits a previously sent chat message. The messageId is received via onACKSendMessage or onMessageReceived when the original message was sent.

ParameterTypeDescription
messageStringThe updated (edited) message text.
messageIdStringUnique ID of the original message to be edited.
typeStringUse "chat-update" to edit a message.
CallbackDelivered ToDescription
onACKUpdateMessageSenderAcknowledgment that the edit request was received.
onMessageUpdateRecipientsDelivers the updated message to all recipients.
val option = JSONObject().apply {
    put("message", "This is my edited message")
    put("messageId", "3889493030")
    put("type", "chat-update")
}

room?.transactMessage(option)

override fun onACKUpdateMessage(data: JSONObject?) {
    // Acknowledgment of the edit request
}

override fun onMessageUpdate(data: JSONObject?) {
    // data contains the updated message
}

Delete a Chat Message

EnxRoom.transactMessage() also handles message deletion. Use "chat-delete" as the type and provide the messageId of the message to remove.

ParameterTypeDescription
messageIdStringUnique ID of the message to be deleted.
typeStringUse "chat-delete" to delete a message.
CallbackDelivered ToDescription
onACKDeleteMessageSenderAcknowledgment that the delete request was received.
onMessageDeleteRecipientsNotifies recipients that a message has been deleted.
val option = JSONObject().apply {
    put("messageId", "3889493030")
    put("type", "chat-delete")
}

room?.transactMessage(option)

override fun onACKDeleteMessage(data: JSONObject?) {
    // Acknowledgment that the deletion was processed
}

override fun onMessageDelete(data: JSONObject?) {
    // data contains deleted message information
}
Custom Signalling

EnxRoom.sendUserData() sends a structured JSON payload to one or more participants without any EnableX message structure constraints. Use this to exchange application-specific instructions, polls, or any custom data during a session.

ParameterTypeDescription
dataJSON ObjectA JSON object with custom keys. Passed to recipients without structure enforcement.
isBroadcastBooleantrue to broadcast to all participants; false to signal specific recipients.
recipientIDsArrayList of client IDs of intended recipients. Not used when isBroadcast is true.
CallbackDescription
onUserDataReceivedDelivers the received custom data as a JSONObject to the intended recipients. Available from Android SDK v1.5.3 and later.
val userData = JSONObject().apply { put("handRaised", true) }
room?.sendUserData(userData, "public", JSONArray())

override fun onUserDataReceived(jsonObject: JSONObject?) { }

room?.userStartTyping()
override fun onUserStartTyping(jsonObject: JSONObject?) { }
Error CodeDescription
5127Exceeding the maximum allowed data transfer rate of 100 Kbps.
File Sharing

File sharing allows participants to upload and download files within an RTC session. Available from Android SDK v1.5.3 and later. You must call setFileShareObserver(this) before using any file sharing API.

Required: Call room.setFileShareObserver(this) after connecting to the room before calling any file sharing methods.

Upload a File

EnxRoom.sendFiles() initiates a file transfer to the EnableX server. A UI is presented to the user to select the file to upload.

ParameterTypeDescription
viewFrameLayoutThe layout where the file-picker UI is displayed.
isBroadcastBooleantrue to share with all participants; false to share with specific users.
clientIdListArrayList of client IDs of intended recipients. Not used when isBroadcast is true.
CallbackDelivered ToDescription
onInitFileUploadSenderNotified when the file upload process is initiated.
onFileUploadedSenderNotified when the file has been uploaded successfully.
onFileUploadFailedSenderNotified when the file upload fails.
onFileUploadStartedReceiversNotified when a file upload begins (file is being uploaded).
onFileAvailableReceiversNotified when a file is ready to download.
room?.setEnxFileShareObserver(myFileShareObserver)

val fileOpts = JSONObject().apply {
    put("name", "document.pdf")
    put("type", "public")
}
room?.sendFiles(fileOpts)

room?.cancelFiles(uploadToken)

override fun onInitFileUpload(jsonObject: JSONObject?) { }
override fun onFileUploadStarted(jsonObject: JSONObject?) { }
override fun onFileUploaded(jsonObject: JSONObject?) { }
override fun onFileAvailable(jsonObject: JSONObject?) {
    val fileInfo = jsonObject?.optJSONObject("fileInfo")
    room?.receiveFiles(fileInfo!!)
}
override fun onFileDownloaded(jsonObject: JSONObject?) { }
override fun onFileUploadCancelled(jsonObject: JSONObject?) { }
override fun onFileDownloadCancelled(jsonObject: JSONObject?) { }
override fun onFileUploadFailed(jsonObject: JSONObject?) { }
override fun onFileDownloadFailed(jsonObject: JSONObject?) { }

Get Available Files

EnxRoom.getAvailableFiles() returns all files currently available for download in the session. Call this after joining the room to retrieve any files shared before you connected.

val myFiles = room?.getAvailableFiles()
// Returns a JSONArray of file info objects, e.g.:
// [ { "name": "report.pdf", "size": 191002, "index": 0 } ]

Download a Shared File

EnxRoom.downloadFile() downloads a file identified by its file info object (received via onFileAvailable or getAvailableFiles()).

ParameterTypeDescription
fileInfoJSON ObjectFile information object obtained from onFileAvailable or getAvailableFiles().
isAutoSaveBooleantrue to save the file automatically (callback includes the saved file path); false to receive Base64-encoded raw data to handle saving manually.
CallbackDescription
onInitFileDownloadNotified when the file download process is initiated.
onFileDownloadedNotified when the file has been downloaded (with or without auto-save).
onFileDownloadFailedNotified when the file download fails.
room?.downloadFile(fileInfoJsonObject, true)

override fun onFileDownloaded(jsonObject: JSONObject?) {
    // File downloaded — jsonObject contains path or Base64 data
}

override fun onFileDownloadFailed(jsonObject: JSONObject?) {
    // Download failed — handle error
}

Cancel a File Upload

Use cancelUpload() to cancel a specific ongoing upload, or cancelAllUploads() to cancel all uploads you initiated.

// Cancel a specific upload job
enxRoom?.cancelUpload(jobId)

// Cancel all ongoing uploads
enxRoom?.cancelAllUploads()

// Acknowledgment callback
override fun onFileUploadCancelled(jsonObject: JSONObject?) {
    // Upload has been cancelled
}
Error CodeDescription
5089Storage access is denied.
5090Failed to save the file.
5091File sharing is not available in this context.
5092Too many files to upload — maximum one file per request.
5098Unable to cancel upload after upload is complete.
5099Failed to cancel — invalid upload ID.
5100Failed to upload a possibly corrupt file.
1182Failed to upload file.
1185File size exceeds the maximum allowed size.

Cancel a File Download

Use cancelDownload() to cancel a specific ongoing download, or cancelAllDownloads() to cancel all downloads at your endpoint.

// Cancel a specific download job
enxRoom?.cancelDownload(jobId)

// Cancel all ongoing downloads
enxRoom?.cancelAllDownloads()

// Acknowledgment callback
override fun onFileDownloadCancelled(jsonObject: JSONObject?) {
    // Download has been cancelled
}
Error CodeDescription
5089Storage access is denied.
5090Failed to save the file.
5101The file is already downloaded.
1181File download is not available. Non-contextual method call.
1183Failed to download the file.
Screen Sharing

Screen sharing publishes the device screen as a video stream (Stream ID 101) at 6 fps. To receive shared screens, subscribe to Stream ID 101. Screen sharing must be enabled when creating the room: { "screen_share": true }.

You must call room.setScreenShareObserver(this) before calling any screen sharing method.

Android 11+ Note: On Android 11 (API level 30) or later, you must create a foreground service with mediaProjection foreground service type declared in your manifest before starting screen sharing. Screen sharing continues even when the application is in the background.

Start Screen Sharing

EnxRoom.startScreenShare() creates and publishes a screen share stream into the room.

CallbackDelivered ToDescription
onScreenSharedStartedEveryone in roomNotifies all participants that screen sharing has started, providing the screen share stream object.
room?.setEnxScreenShareObserver(myScreenShareObserver)

room?.startScreenShare()

override fun onStartScreenShareACK(jsonObject: JSONObject?) {
    // ACK to the initiator
}

override fun onScreenSharedStarted(enxStream: EnxStream?) {
    enxStream?.attachRenderer(screenShareView)
}

Stop Screen Sharing

EnxRoom.stopScreenShare() stops the active screen sharing session initiated by the local user.

CallbackDelivered ToDescription
onScreenSharedStoppedEveryone in roomNotifies all participants that screen sharing has stopped.
room?.stopScreenShare()

override fun onStoppedScreenShareACK(jsonObject: JSONObject?) { }

override fun onScreenSharedStopped(enxStream: EnxStream?) {
    enxStream?.detachRenderer(screenShareView)
}
Error CodeDescription
5107Repeated startScreenShare() call while a previous request is in process.
1170Screen sharing is not supported in your subscription.

Force Stop Sharing (Moderator Only)

EnxRoom.stopAllSharing() allows a moderator to force stop any ongoing screen sharing or canvas streaming by any participant in the room. This method is restricted to moderators and is not available to regular participants.

Moderator only: stopAllSharing() can only be called by a moderator. It stops both screen sharing and canvas streaming. Available from Android SDK v2.1.2 and later.
CallbackDelivered ToDescription
onStopAllSharingACKEveryone in roomNotifies all participants that all sharing has been stopped by the moderator.
// Moderator force-stops all screen sharing and canvas streaming
EnxRoom.stopAllSharing()

override fun onStopAllSharingACK(jsonObject: JSONObject?) {
    // All sharing has been stopped — update your UI accordingly
}
Canvas Streaming

Canvas streaming publishes any Android View as a video stream (Stream ID 102) into the room. Canvas streaming must be enabled when creating the room: { "canvas": true }. To receive a canvas stream, subscribe to Stream ID 102.

Start Canvas Streaming

EnxRoom.startCanvas() starts publishing the specified view as a canvas stream into the room.

CallbackDelivered ToDescription
onStartCanvasAckPublisherAcknowledgment to the publisher when canvas streaming starts.
onCanvasStartedEveryone in roomNotifies all participants that canvas streaming has started, providing the canvas stream object.
room?.setEnxCanvasObserver(myCanvasObserver)

val opts = JSONObject().apply {
    put("url", "https://your-canvas-url.com")
}
room?.startCanvas(opts)

override fun onStartCanvasAck(jsonObject: JSONObject?) { }
override fun onCanvasStarted(enxStream: EnxStream?) {
    enxStream?.attachRenderer(canvasView)
}
Error CodeDescription
5103Canvas streaming or screen sharing is already active in the room.
5105Repeated startCanvas() call when canvas stream is already active.
5107Repeated startCanvas() call while a previous request is being processed.
5110Failed to publish the canvas stream.

Stop Canvas Streaming

EnxRoom.stopCanvas() stops the active canvas streaming session.

CallbackDelivered ToDescription
onStoppedCanvasAckPublisherAcknowledgment to the publisher when canvas streaming stops.
onCanvasStoppedEveryone in roomNotifies all participants that canvas streaming has stopped.
room?.stopCanvas()

override fun onStoppedCanvasAck(jsonObject: JSONObject?) { }
override fun onCanvasStopped(enxStream: EnxStream?) {
    enxStream?.detachRenderer(canvasView)
}
Note: A moderator can force stop canvas streaming using stopAllSharing(). See Force Stop Sharing above. Available from Android SDK v2.1.2 and later.
Annotation

Annotation allows users to draw on a remote stream. To enable annotation, canvas streaming must be enabled when creating the room: { "canvas": true }. Available from Android SDK v2.1.2 and later.

You must add the annotation toolbar to your layout XML and set the setAnnotationObserver after connecting to the room.

Add Annotation Toolbar to Layout

<enx_rtc_android.annotations.EnxAnnotationsToolbar
    android:id="@+id/annotations_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

Start Annotation

EnxRoom.startAnnotation() begins annotation on a given stream object.

CallbackDelivered ToDescription
onStartAnnotationAckAnnotatorAcknowledgment to the annotator when annotation starts.
onAnnotationStartedEveryone in roomNotifies all participants that annotation has started.
room?.setEnxAnnotationObserver(myAnnotationObserver)

room?.startAnnotation(JSONObject())

override fun onStartAnnotationAck(jsonObject: JSONObject?) { }
override fun onAnnotationStarted(enxStream: EnxStream?) { }

Stop Annotation

EnxRoom.stopAnnotation() stops the current annotation.

CallbackDelivered ToDescription
onStoppedAnnotationAckAnnotatorAcknowledgment to the annotator when annotation stops.
onAnnotationStoppedEveryone in roomNotifies all participants that annotation has stopped.
room?.stopAnnotation()

override fun onStoppedAnnotationAck(jsonObject: JSONObject?) { }
override fun onAnnotationStopped(enxStream: EnxStream?) { }
Error CodeDescription
5093Annotation access is denied.
5094Repeated stopAnnotation() while a previous request is in process.
5104Repeated startAnnotation() — annotations are already active in the room.
5106Repeated startAnnotation() while a previous request is in process.
5108Invalid stream passed to startAnnotation().
5109Failed to publish annotation stream.
5112Annotation is only supported in landscape mode.
Live Transcription

Live transcription converts the speech of all Active Talkers in a session to text in near real time. All endpoints that request transcription subscribe to the same transcription feed. The process starts when the first user requests it and stops when the last subscriber opts out — unless auto_transcribe is enabled at the room level, in which case it runs for the full session.

Subscription required: Live transcription is a subscription-based service. Contact your EnableX Account Manager to enable it. If not subscribed, rooms configured with live transcription settings will be rejected.

Start Live Transcription

Two methods are available to start live transcription:

When the method is called for the first time in a session, it starts the transcription process and subscribes the endpoint. Subsequent calls from other endpoints only subscribe them to the existing feed.

CallbackDescription
onACKStartLiveTranscriptionAcknowledgment that the start request was received.
onSelfTranscriptionOnNotifies the endpoint that self-transcription is enabled.
onRoomTranscriptionOnNotifies when transcription is promoted to room-level.
onTranscriptionEventsDelivers live transcription events containing recognized text.

Transcription Event Payload

The onTranscriptionEvents callback delivers a JSONObject with the following fields:

FieldDescription
type"speech_recognising" — intermediate event while audio is being recognized. "speech_recognised" — final event when a phrase is fully recognized (typically at a pause or speech end).
textThe transcribed text string.
durationDuration from the offset at which the speech was identified.
clientIdClient ID of the user whose speech is being recognized.
// Start self-transcription
enxRoom?.startLiveTranscription("english_us")

// Or start room-level transcription
enxRoom?.startLiveTranscriptionForRoom("english_us")

override fun onACKStartLiveTranscription(jsonObject: JSONObject?) {
    // Start request acknowledged
}

override fun onSelfTranscriptionOn(jsonObject: JSONObject?) {
    // This endpoint is now receiving transcription
}

override fun onRoomTranscriptionOn(jsonObject: JSONObject?) {
    // All subscribed endpoints are receiving transcription
}

override fun onTranscriptionEvents(jsonObject: JSONObject?) {
    val type     = jsonObject?.getString("type")     // "speech_recognising" or "speech_recognised"
    val text     = jsonObject?.getString("text")     // Transcribed text
    val clientId = jsonObject?.getString("clientId") // Speaker's client ID
    // Display or process the transcribed text
}
Error CodeDescription
3002Live transcription subscription is not enabled.
3002Live transcription is already in progress.

Stop Live Transcription

EnxRoom.stopLiveTranscription() unsubscribes the calling endpoint from the live transcription feed. When the last subscribed endpoint calls this method, the transcription process stops in the room — unless auto_transcribe is enabled at the room level, in which case it continues until the session ends.

CallbackDescription
onACKStopLiveTranscriptionAcknowledgment that the stop request was received.
onSelfTranscriptionOffNotifies the endpoint that self-transcription has been turned off.
onRoomTranscriptionOffNotifies when room-level transcription has been stopped.
enxRoom?.stopLiveTranscription()

override fun onACKStopLiveTranscription(jsonObject: JSONObject?) {
    // Stop request acknowledged
}

override fun onSelfTranscriptionOff(jsonObject: JSONObject?) {
    // Hide transcription UI
}

override fun onRoomTranscriptionOff(jsonObject: JSONObject?) {
    // Transcription has ended for all participants
}
Error CodeDescription
3001Live transcription request not found — transcription may not have been started.