Skip to main content
Version: 5.21.0

Delegates and event listeners

To react to SDK events, integrators have two mechanisms:

  1. ChatCenterUIListener — an interface with 4 callback methods: unread counter, network error, link click, internal SDK exception. Sufficient for most integrations.
  2. ChatUpdateProcessor — a SharedFlow bus for message delivery events, status changes, and connection state. Used only when building a custom UI on top of the SDK.

ChatCenterUIListener

fun setChatCenterUIListener(listener: ChatCenterUIListener)

Subscribes your app to UI events and basic SDK events. Call it after init(...) — otherwise the SDK throws IllegalStateException. A repeated call replaces the previous listener (older subscriptions on streams inside the SDK are cancelled).

Interface methods

MethodParameterWhen called
unreadMessageCountChanged(count: UInt)unread countImmediately after setChatCenterUIListener(...) (the current value), then whenever the counter changes — authorize(...), a new incoming message, a read receipt by the operator
networkErrorReceived(error: Error)edna.chatcenter.core.main.Error — fields and a handling example are in Errors → networkErrorReceivedA network error from the server or WebSocket
urlClicked(url: String)URLThe user tapped a link in a message
exceptionReceived(trace: String)stack traceInternal SDK exception (for logging)

Example

import android.content.Intent
import edna.chatcenter.core.main.ChatCenterUIListener
import edna.chatcenter.core.main.Error // important: shadows kotlin.Error — if needed, use an alias `as SdkError`

private const val APP_UNREAD_COUNT_BROADCAST = "com.example.app.UNREAD_COUNT"
private const val UNREAD_COUNT_KEY = "unread_count"

chatCenterUI.setChatCenterUIListener(object : ChatCenterUIListener {
override fun unreadMessageCountChanged(count: UInt) {
val intent = Intent(APP_UNREAD_COUNT_BROADCAST)
.putExtra(UNREAD_COUNT_KEY, count.toInt())
applicationContext.sendBroadcast(intent)
}

override fun networkErrorReceived(error: Error) {
Log.e("ChatCenter", "Network error [${error.code}]: ${error.message}")
}

override fun urlClicked(url: String) {
Log.i("UrlClicked", url)
}
})

Callback threads

CallbackThread
unreadMessageCountChangedmain — you can update the UI directly
exceptionReceivedmain
urlClickedmain (comes from the link click handler in the UI)
networkErrorReceivedbackground (OkHttp / Retrofit / @WorkerThread sources) — switch to main explicitly for UI

Recommended idiom for networkErrorReceived when you need to touch the UI:

override fun networkErrorReceived(error: Error) {
// This callback arrives from a network thread, not main.
// Use your screen's lifecycleScope / viewModelScope.
lifecycleScope.launch(Dispatchers.Main) {
showErrorToUser(error)
}
}

For View-based code outside a coroutine context, view.post { ... } or Handler(Looper.getMainLooper()).post { ... } are acceptable — but if the project already uses coroutines, stick with one idiom (Dispatchers.Main).

A detailed rationale (where and why the callback is invoked) with concrete call sites is in Known limitations.

Advanced scenarios

Advanced scenario — custom UI on top of the SDK

The section below is needed only if you are building your own message list / status indicators on top of the SDK or monitoring SDK events at a low level. For the unread badge, network errors, and link clicks, the ChatCenterUIListener above is sufficient.

Subscribing to additional events — ChatUpdateProcessor

If your scenario needs events that are not in ChatCenterUIListener (for example, the exact moment a message is delivered to the server or a signal that an offline socket has closed), the reactive ChatUpdateProcessor bus from the edna.chatcenter.core.chatUpdates package is available. The class exposes public MutableSharedFlow streams. Below are 6 base flows for a custom UI; in addition, the class has streams for quick replies, the typing indicator, attachment updates, and file download progress — they are exposed as fields of the same class; see the KDoc in the sources.

FlowWhat is emittedWhen useful
newMessageFlowChatItem — a chat history item added after the server response (including outgoing items received in GET_MESSAGES)Custom notification/counter in addition to the standard push
messageSendSuccessFlowChatItemProviderData (uuid, messageId, sentAt) — server confirmation that the outgoing message was acceptedDelivery confirmation on the app side
messageSendErrorFlowChatItemSendErrorModelReaction to a send error (retry strategy)
outgoingMessageStatusChangedFlowList<Status> — a batch of status updates (Status.status takes a MessageStatus value); a single emit may contain statuses for different messagesRendering "checkmarks" in a custom UI
socketIsClosedFlowInt — the WebSocket close codeOffline mode indicator
cleanAllOnUiFlowA signal to clear the UIReset custom state — emitted in both logout() scenarios (both the deferred cleanup during a handshake and the full cleanup)

Get an instance via the inject() delegate of the SDK's public DI container:

import edna.chatcenter.core.chatUpdates.ChatUpdateProcessor
import edna.chatcenter.core.serviceLocator.core.inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

val processor: ChatUpdateProcessor by inject()

// ChatUpdateProcessor emits from Dispatchers.Unconfined — events do not arrive on
// the main thread (they arrive on the thread where the SDK's internal emit() ran).
// Wrap UI calls in withContext(Dispatchers.Main). See Known limitations for details.
lifecycleScope.launch {
processor.newMessageFlow.collect { item ->
withContext(Dispatchers.Main) {
// UI update
}
}
}
inject() is the SDK's public DI container, not Hilt/Koin

The inject() delegate belongs to the public package edna.chatcenter.core.serviceLocator.core and is unrelated to your application's DI frameworks (Hilt, Koin, Dagger).

Additional models for a custom UI

You can work with these types when building your own chat interface (message list, status indicators, file download progress). You do not need to create instances manually — the SDK emits them itself via ChatUpdateProcessor or passes them in callbacks.

FileDescription — attachment model

edna.chatcenter.core.models.FileDescription — a file attachment model that the SDK emits for chat history items (outgoing messages store the list as UserPhrase.files, incoming messages do the same).

Key fields: fileUri: Uri?, size: Long, from: String?, state: MutableStateFlow<AttachmentStateEnum> (default ANY; the SDK updates it itself — read via state.value / state.collect { ... }, do not modify), errorCode: ErrorStateEnum (default ANY), downloadPath: String?.

AttachmentStateEnum (ANY, PENDING, ERROR, EXPIRED, READY) and ErrorStateEnum are public enums from the same package (edna.chatcenter.core.models.enums).

ProgressReceiver — file download events

edna.chatcenter.core.broadcastReceivers.ProgressReceiver is a BroadcastReceiver through which the SDK reports file download progress. Register it if you need to show your own progress indicator. Action constants are declared in the companion object of ProgressReceiver:

  • ProgressReceiver.PROGRESS_BROADCAST — progress update (0..100).
  • ProgressReceiver.DOWNLOADED_SUCCESSFULLY_BROADCAST — the file has been downloaded.
  • ProgressReceiver.DOWNLOAD_ERROR_BROADCAST — download error.

The intent contains FileDescription as a Parcelable extra under the key FileDownloadWorker.FD_TAG (edna.chatcenter.core.workers.FileDownloadWorker.FD_TAG). For DOWNLOAD_ERROR_BROADCAST, a Throwable is also passed as a Serializable extra under the key ProgressReceiver.DOWNLOAD_ERROR_BROADCAST (the same constant is used as the action).

MessageStatus — message status enum

Described in the canonical section Messages → Message statuses. Used to build custom "checkmark" indicators (the sentState field of sent history items).

  • Messagessend(), prefill(), unread counter.
  • Errors — handling Error from networkErrorReceived.
  • Known limitations — coroutine scope nuances of the advanced event bus.