Перейти к основному содержимому
Версия: 5.21.0

Делегаты и слушатели событий

Для реакции на события SDK у интегратора есть два механизма:

  1. ChatCenterUIListener — интерфейс с 4 callback-методами: счётчик непрочитанных, сетевая ошибка, клик по ссылке, внутреннее исключение SDK. Достаточно для большинства интеграций.
  2. ChatUpdateProcessorSharedFlow-шина для событий уровня доставки сообщений, изменения статусов и состояния соединения. Используется только при построении кастомного UI поверх SDK.

ChatCenterUIListener

fun setChatCenterUIListener(listener: ChatCenterUIListener)

Подписывает приложение на события UI и базовые SDK-события. Вызывать после init(...) — иначе SDK выбросит IllegalStateException. Повторный вызов заменяет предыдущий listener (старые подписки на потоки внутри SDK отменяются).

Методы интерфейса

МетодПараметрКогда вызывается
unreadMessageCountChanged(count: UInt)количество непрочитанныхСразу после setChatCenterUIListener(...) (текущее значение), затем при изменении счётчика — authorize(...), получение нового входящего сообщения, прочтение оператором
networkErrorReceived(error: Error)edna.chatcenter.core.main.Error — поля и пример обработки см. в Ошибки → networkErrorReceivedСетевая ошибка от сервера или WebSocket
urlClicked(url: String)URLПользователь нажал на ссылку в сообщении
exceptionReceived(trace: String)стек-трейсВнутреннее исключение SDK (для логирования)

Пример

import android.content.Intent
import edna.chatcenter.core.main.ChatCenterUIListener
import edna.chatcenter.core.main.Error // важно: затеняет kotlin.Error — при необходимости используйте 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", "Сетевая ошибка [${error.code}]: ${error.message}")
}

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

Потоки callback'ов

CallbackПоток
unreadMessageCountChangedmain — можно обновлять UI напрямую
exceptionReceivedmain
urlClickedmain (приходит из обработчика клика по ссылке в UI)
networkErrorReceivedфоновый (OkHttp / Retrofit / @WorkerThread-источники) — для UI переключайтесь на main явно

Рекомендуемый идиом для networkErrorReceived, когда нужно тронуть UI:

override fun networkErrorReceived(error: Error) {
// Этот callback приходит с сетевого потока, не с main.
// Используйте lifecycleScope / viewModelScope вашего экрана.
lifecycleScope.launch(Dispatchers.Main) {
showErrorToUser(error)
}
}

Для View-based кода вне coroutine-контекста допустимы view.post { ... } или Handler(Looper.getMainLooper()).post { ... } — но если в проекте уже используются корутины, держитесь одного идиома (Dispatchers.Main).

Подробное обоснование (где и почему вызывается callback) с конкретными call-sites — в Известных ограничениях.

Продвинутые сценарии

Продвинутый сценарий — кастомный UI поверх SDK

Раздел ниже нужен только если вы строите собственный список сообщений / индикаторы статусов поверх SDK или мониторите события SDK на низком уровне. Для бейджа непрочитанных, сетевых ошибок и кликов по ссылкам достаточно ChatCenterUIListener выше.

Подписка на дополнительные события — ChatUpdateProcessor

Если в вашем сценарии нужны события, которых нет в ChatCenterUIListener (например, точный момент доставки сообщения на сервер или сигнал закрытия офлайн-сокета), доступна реактивная шина ChatUpdateProcessor из пакета edna.chatcenter.core.chatUpdates. Класс предоставляет публичные MutableSharedFlow-потоки. Ниже описаны 6 базовых для кастомного UI; помимо них в классе есть потоки для quick replies, typing-индикатора, обновления вложений и прогресса загрузки файлов — доступны как поля того же класса, см. KDoc исходников.

ПотокЧто эмититсяКогда полезно
newMessageFlowChatItem — элемент истории чата, добавленный после ответа сервера (включая исходящие, пришедшие в GET_MESSAGES)Кастомное оповещение/счётчик помимо штатного push'а
messageSendSuccessFlowChatItemProviderData (uuid, messageId, sentAt) — подтверждение от сервера, что исходящее сообщение принятоПодтверждение доставки на стороне приложения
messageSendErrorFlowChatItemSendErrorModelРеакция на ошибку отправки (retry-стратегия)
outgoingMessageStatusChangedFlowList<Status> — пачка обновлений статусов (Status.status принимает значение MessageStatus); в одном эмитте — статусы разных сообщенийОтображение «галочек» в кастомном UI
socketIsClosedFlowInt — код закрытия WebSocketИндикатор офлайн-режима
cleanAllOnUiFlowСигнал на очистку UIСброс кастомного состояния — эмитится в обоих сценариях logout() (как при отложенной очистке во время хендшейка, так и при полной)

Получить экземпляр — через inject()-делегат публичного DI-контейнера SDK:

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 эмитит из Dispatchers.Unconfined — события приходят не на Main
// thread (на потоке, где сработал emit() внутри SDK). Перед UI-вызовами оборачивайте
// код в withContext(Dispatchers.Main). Подробности — в Известных ограничениях.
lifecycleScope.launch {
processor.newMessageFlow.collect { item ->
withContext(Dispatchers.Main) {
// обновление UI
}
}
}
inject() — публичный DI-контейнер SDK, не Hilt/Koin

Делегат inject() принадлежит публичному пакету edna.chatcenter.core.serviceLocator.core и не связан с DI-фреймворками вашего приложения (Hilt, Koin, Dagger).

Дополнительные модели для кастомного UI

Этими типами вы можете оперировать при построении собственного интерфейса чата (списка сообщений, индикаторов статусов, прогресса скачивания файлов). Создавать их экземпляры вручную не нужно — SDK эмитит их сам через ChatUpdateProcessor или передаёт в callback'ах.

FileDescription — модель вложения

edna.chatcenter.core.models.FileDescription — модель файлового вложения, которую SDK эмитит для элементов истории чата (исходящие сообщения хранят список как UserPhrase.files, входящие — аналогично).

Ключевые поля: fileUri: Uri?, size: Long, from: String?, state: MutableStateFlow<AttachmentStateEnum> (default ANY; SDK обновляет сам — читайте через state.value / state.collect { ... }, не модифицируйте), errorCode: ErrorStateEnum (default ANY), downloadPath: String?.

AttachmentStateEnum (ANY, PENDING, ERROR, EXPIRED, READY) и ErrorStateEnum — публичные enum'ы из того же пакета (edna.chatcenter.core.models.enums).

ProgressReceiver — события скачивания файлов

edna.chatcenter.core.broadcastReceivers.ProgressReceiverBroadcastReceiver, через который SDK сообщает о ходе скачивания файлов. Регистрируйте, если нужно отображать собственный индикатор прогресса. Константы actions объявлены в companion object самого ProgressReceiver:

  • ProgressReceiver.PROGRESS_BROADCAST — обновление прогресса (0..100).
  • ProgressReceiver.DOWNLOADED_SUCCESSFULLY_BROADCAST — файл скачан.
  • ProgressReceiver.DOWNLOAD_ERROR_BROADCAST — ошибка скачивания.

Intent содержит FileDescription как Parcelable-extra под ключом FileDownloadWorker.FD_TAG (edna.chatcenter.core.workers.FileDownloadWorker.FD_TAG). Для DOWNLOAD_ERROR_BROADCAST дополнительно передаётся Throwable через Serializable-extra под ключом ProgressReceiver.DOWNLOAD_ERROR_BROADCAST (та же константа используется и в качестве action).

MessageStatus — enum статусов сообщения

Описан в каноническом разделе Сообщения → Статусы сообщения. Используется для построения кастомных индикаторов «галочек» (поле sentState отправленных элементов истории).

Связанные разделы