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

Известные ограничения 5.x

Эта страница описывает параметры публичного API SDK, которые в текущей версии (5.x) не применяются или применяются с ограничениями, а также поведенческие особенности, которые нужно учесть при интеграции. Параметры, не вошедшие в эту таблицу, работают как задокументировано.

Параметры с приоритетом серверной настройки

Перечисленные ниже свойства ChatConfig помечены @Deprecated. Они применяются рантаймом как fallback — если для соответствующей настройки не пришло значение с сервера. Формат применения в коде: serverValue ?: clientValue — серверная настройка всегда побеждает.

Для production не полагайтесь на клиентские значения: серверная конфигурация может переопределить их без обновления приложения.

ПараметрПоведениеЗамечания
ChatConfig.keepWebSocketActiveFallback к клиентскому значению, если сервер не прислал keepSocketActiveПодвержено стандартным ограничениям фоновой работы Android (Doze, App Standby) — конкретного behavior change для WebSocket в Android 15 нет
ChatConfig.keepSocketActiveDuringOperatorSessionFallback к клиентскому значению
ChatConfig.searchEnabledFallback к клиентскому значению; управляет видимостью UI-поиска по истории
ChatConfig.linkPreviewEnabledFallback к клиентскому значению; включает превью ссылок (OpenGraph)
ChatConfig.voiceRecordingEnabledFallback к клиентскому значению; управляет видимостью кнопки записи голоса
ChatConfig.autoScrollToLatestFallback к клиентскому значению; маппится на серверное поле scrollToLatestИмена клиентского и серверного полей отличаются
ChatConfig.surveyCompletionDelayFallback к клиентскому значению; дефолт 3 сек, если значение не задано ни клиентом, ни сервером
ChatConfigCore.historyLoadingCountПоле объявлено как val — переопределить через ChatConfig нельзя. Используется как fallback при отсутствии серверной настройкиМенять значение можно только пересборкой ChatConfigCore целиком

Поля без эффекта в текущей версии

ПараметрПоведениеЗамечания
ChatFlow.fullScreenModeПомечено @Deprecated («с момента targetSdk = 35 в ChatCenterUI данный параметр более не используется — всегда true»), рантаймом не читается. Edge-to-edge режим определяется поведением Android в приложении-интеграторе при targetSdk = 35 и темой вашей ActivityУстановка значения не оказывает эффекта
ChatTexts (целиком)Все поля помечены @Deprecated. Для локализации UI-строк переопределяйте ecc_*-ключи в strings.xmlСм. Локализация

Поведение при разрыве WebSocket-соединения

Начиная с версии 5.21.0 в SDK реализовано автоматическое переподключение к WebSocket. По умолчанию оно выключено и включается параметром isReconnectEnabled в WSConfig — см. Network config.

Если автоматическое переподключение не включено

Когда isReconnectEnabled = false (значение по умолчанию), после разрыва WebSocket сокет закрывается, новые сообщения не отправляются и не приходят, а ожидающие в очереди остаются в статусе PENDING / FAILED до восстановления сессии.

Что нужно сделать на стороне приложения:

  • Подпишитесь на ConnectivityManager.NetworkCallback, чтобы отслеживать восстановление сети;
  • При восстановлении сети повторно вызовите chatCenterUI.authorize(user, auth). Добавьте на стороне приложения guard от повторных вызовов с теми же параметрами — SDK не делает early-return и при идентичных аргументах переустанавливает внутреннее соединение;
  • Покажите пользователю офлайн-индикатор до восстановления сессии;
  • Реакцию на разрыв обрабатывайте через ChatCenterUIListener.networkErrorReceived(error) — см. Методы → Errors. Этот callback приходит не на main thread — рекомендуемый идиом переключения и полную таблицу потоков см. в Делегаты → Потоки callback'ов.

Экран восстановления состояния

Если экраны SDK (чат, галерея вложений, диалоги SDK) открываются системой до того, как приложение успело вызвать init(...) / initAsync(...), SDK защищает интеграцию от падений:

  • поверх ChatFragment отображается полноэкранный плейсхолдер с надписью «Восстановление состояния…» (строка ecc_restoring_state);
  • галерея вложений (ImagesActivity) и диалоги SDK (BottomSheet, Dialog) закрываются автоматически.

Сценарий возникает, например, при системном пересоздании активити (Activity recreation, low memory), когда пользовательский процесс был убит, а Android восстановил последний экран до того, как ваш Application.onCreate успел проинициализировать SDK.

Что нужно сделать на стороне приложения:

  • Вызывайте init(...) / initAsync(...) как можно раньше — в Application.onCreate, а не в Activity.onCreate. Это сокращает время отображения плейсхолдера до минимума.
  • Если у вас лаунчер-активити выполняет дополнительные действия перед init(...), рассмотрите переход на асинхронную инициализацию initAsync(...), чтобы UI приложения не зависел от тяжёлых операций SDK.
  • Цвета плейсхолдера и текст можно переопределить — см. Дизайн-система → Цвета → Экран восстановления состояния и Локализация.

SSL

Не включайте allowUntrustedCertificates = true в production-сборке

Параметр предназначен только для development-сборки против локального тестового сервера. При установке в true полностью отключается TLS-проверка и соединение становится уязвимым к MITM. Значение флага не зависит от типа сборки — если его случайно оставить, он сработает и в release.

Что нужно сделать перед релизом:

  • Явно установите SSLPinningConfig(allowUntrustedCertificates = false) в production-конфиге;
  • Не читайте значение из remote-config / env, который может быть переключён в продакшене;
  • Не переопределяйте значение через BuildType-overrides в release-сборке.

См. также: Network config и Troubleshooting.

Поведенческие особенности

Гонка при параллельном вызове методов ChatCenterUI

Вызывайте методы ChatCenterUI только с главного потока

Методы ChatCenterUI (init(), authorize(), logout(), send() и др.) необходимо вызывать только с главного потока. Параллельный вызов из нескольких потоков не поддерживается и может привести к нежелательным эффектам — например, к повторной регистрации push-токена или к рассинхронизации между WebSocket-сессией и локальным состоянием.

Что нужно сделать на стороне приложения:

  • вызывайте методы ChatCenterUI только с main thread; если требуется вызов из фонового потока — оборачивайте через runOnUiThread { ... } или Handler(Looper.getMainLooper()).post { ... };
  • если в приложении несколько точек, которые могут вызвать authorize(...) (например, push-обработчик и splash screen), добавьте собственный guard / сериализацию вызовов на стороне приложения;
  • не вызывайте authorize(...) повторно «на всякий случай» — при идентичных параметрах SDK переустанавливает внутреннее соединение (см. также раздел «Поведение при разрыве WebSocket-соединения»).
ChatConfig.equals() нестабилен между API levels

Реализация equals() для ChatConfig сравнивает поле notificationImportance только начиная с Android 7.0 (API 24, Build.VERSION_CODES.N). На более старых API два конфига с разными notificationImportance будут считаться равными, на API ≥ 24 — нет.

Симптом: объекты ChatConfig нельзя надёжно использовать как ключ в HashMap/Set или сравнивать через == в логических условиях, особенно если у вас в кодовой базе минимальный API ниже 24. Храните единственный экземпляр конфига и проверяйте идентичность по ===.

UnreadMessagesController — enum-singleton

UnreadMessagesController доступен как INSTANCE-singleton. Это упрощает доступ к контроллеру в продакшене, но усложняет unit-тесты: подменить INSTANCE на тестовый double без рефлексии нельзя.

Что нужно сделать на стороне приложения: оборачивайте UnreadMessagesController в собственный интерфейс/фасад вашего приложения и инжектите этот фасад в код, который требует unit-тестирования.

ChatAuthType.COOKIES — без референс-примера

В enum-классе ChatAuthType есть значение COOKIES, но в публичной документации задокументирован только HEADERS. COOKIES рабочий, но без покрывающих примеров и регрессионных тестов; используйте только при предварительном согласовании с поддержкой edna.

ChatUpdateProcessor coroutine scopes

Подписки на продвинутую шину ChatUpdateProcessor могут прилетать на любой thread

В ChatUpdateProcessor каждый postX(...)-метод эмитит событие из нового CoroutineScope(Dispatchers.Unconfined) — поэтому коллектор может получить событие на потоке OkHttp WebSocket или ином произвольном.

Не используйте flowOn(Dispatchers.Main) — этот оператор меняет контекст upstream-эмиттера, а не вашего коллектора, и в данном случае ничего не переключит.

Корректные варианты:

import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
chatUpdateProcessor.newMessageFlow.collect { item ->
withContext(Dispatchers.Main) {
// безопасные UI-вызовы
}
}
}
}

lifecycleScope стартует на Dispatchers.Main.immediate, поэтому без withContext уже корректно переключитесь на main, если ваш collect-блок не делает фоновую работу.

Какие callback'и на каком потоке. unreadMessageCountChanged, exceptionReceived, urlClicked доставляются на main thread. networkErrorReceived всегда приходит с фонового потока. Резюме потоков и рекомендуемый идиом переключения — в каноническом разделе Делегаты → Потоки callback'ов.

Подробнее о подписках на эту шину — Методы → Делегаты → Продвинутые сценарии.

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