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

Расширенные настройки

Отслеживание событий внутри SDK

fun setChatCenterUIListener(listener: ChatCenterUIListener) - содержит методы, вызываемые при изменении состояний SDK.

/**
* Описывает методы счетчика непрочитанных сообщений,
* получения сетевой ошибки, реакции на нажатие ссылки в сообщении
*/
interface ChatCenterUIListener {
/**
* Изменился счетчик непрочитанных сообщений
* @param count количество непрочитанных сообщений
*/
fun unreadMessageCountChanged(count: UInt) {}

/**
* Получен ответ от сервера с ошибкой
* @param error описание текущей ошибки
*/
fun networkErrorReceived(error: Error) {}

/**
* Нажата ссылка в сообщении
* @param url строка ссылки
*/
fun urlClicked(url: String) {}
}

Чтобы подписаться на изменение количества непрочитанных сообщений, можно задать слушатель:

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

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

Первый раз проверка непрочитанных запускается при инициализации СДК (если пользователь установлен). Для получения обновлений необходим активный чат (открытый и хранимый в памяти). Если нужно дать пользователю возможность выйти с экрана, но необходимо отображать актуальный счетчик, при инициализации библиотеки следует установить флаг keepWebSocketActive = true внутри ChatConfig. В случае необходимости работы счетчика до входа в чат, необходимо устанавливать пользователя через метод forceAuthorize(...), а так же установить флаг keepWebSocketActive = true

Отправка сообщений

Если вы хотите вручную отправить сообщение, можно вызвать внутри объекта ChatCenterUI метод send(message: ChatMessage)

Настройки сервера по умолчанию позволяют отправлять файлы размером до 30 мб.

SSL Pinning

Позволяет использовать указанный список сертификатов для проверки их соответствия с сертификатом на сервере.

осторожно

При использования данного функционала, не рекомендуется использовать только один сертификат. В случае его отзыва или истечения срока действия - SDK перестанет подключаться к серверу. Используйте резервные сертификаты с их своевременным обновлением.

Для включения SSL pinning необходимо:

  1. В папку res/raw поместить публичные сертификаты.
  2. В ChatConfig пробросить класс ChatNetworkConfig (поле networkConfig), указав сертификаты:
val networkConfig = ChatNetworkConfig(
HTTPConfig(),
WSConfig(),
SSLPinningConfig(certificates, server.allowUntrustedSSLCertificate)
)

val chatConf = ChatConfig(
transportConfig,
networkConfig,
//...
)

Поле allowUntrustedSSLCertificate отключает проверку сертификатов. Все сертификаты будут считаться доверенными.

Настройка таймаутов подключения

Таймауты настраиваются с помощью классов HttpConfig и WSConfig. Объекты данных классов входят в класс ChatNetworkConfig, который, в свою очередь, явялется полем класса ChatConfig. Единица измерения таймаутов в класса HttpConfig и WSConfig - секунды.

Использование внутренних диплинков

Библиотека позволяет использовать внутренние диплинки. Например, если в сообщении встречается текст вида:

earth://some.params?code={code}

И если вы создадите Activity, который будет запускаться Аction.VIEW, то при клике на подобную ссылку запустится ваш указанный активити. Для этого в манифесте указать для вашего активити фильтры:

<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="earth"
android:host="*" />
</intent-filter>

Настройки backup для приложения

В библиотеке используется настройка

<application
android:fullBackupContent="@xml/backup_rules">
...
</application>

Содержимое данного файла:

<full-backup-content>
<exclude domain="sharedpref" path="im.threads.internal.utils.EncryptedPrefStore.xml"/>
</full-backup-content>

Данная запись необходима, чтобы зашифрованные SharedPreferences не оставались в памяти устройства после переустановки приложения. Если вы используете свой собственный fullBackupContent файл, вам необходимо добавить в ваш файл exclude, который описан у нас и затем переопределить ваш файл своим:

<application
android:fullBackupContent="@xml/your_backup_rules"
tools:replace="android:fullBackupContent">
...
</application>

Бывает так, что другие SDK также используют android:fullBackupContent настройку. В этом случае нужно посмотреть, какие исключения прописаны в этих SDK и сделать общий файл. Например у Vungle и AppsFlyer есть свои настройки fullBackupContent. Их исключения задокументированы следующим образом:

Vungle - https://support.vungle.com/hc/en-us/articles/360047780372#vungle-exclusion-rules-0-11
AppsFlyer - https://support.appsflyer.com/hc/en-us/articles/207032126-Android-SDK-integration-for-developers#integration-backup-rules

Для объединения их настроек с нашей должен получиться следующий файл:

<full-backup-content>
<exclude domain="sharedpref" path="appsflyer-data"/>
<exclude domain="file" path="vungle" />
<exclude domain="file" path="vungle_cache" />
<exclude domain="external" path="vungle_cache" />
<exclude domain="database" path="vungle_db" />
<exclude domain="sharedpref" path="com.vungle.sdk.xml" />
<exclude domain="sharedpref" path="im.threads.internal.utils.EncryptedPrefStore.xml"/>
</full-backup-content>

Логгер

Библиотека использует свой собственный логгер, который поддерживает запись в файл. По умолчанию он выключен, то есть логи не будут выводиться ни в файл, ни в консоль. Чтобы включить логи в библиотеке, создайте объект ChatLoggerConfig и передайте его в ChatCenterUI при инициализации библиотеки. Пример:

val loggerConfig = ChatLoggerConfig(
applicationContext,
logFileSize = 50
)

chatCenterUI = ChatCenterUI(applicationContext, loggerConfig)

Если у вас возникла проблема в процессе работы SDK, данные логи необходимо собрать и предоставить в службу поддержки (также добавьте скриншоты или видео с проблемой). Для сбора откройте страницу чата и потрясите телефон. Появится всплывающее сообщение с предложением отправить логи любым удобным вам способом: почта, мессенджер и т.д.

Результат шейка: меню отправки логов

Меню отправки логов

В случае, если вы отправляете логи с эмулятора, отправьте при открытом чате в терминал команду:

adb emu sensor set acceleration 50:50:50; sleep 0.1; adb emu sensor set acceleration 0:0:0

Иногда эмулятор реагирует на такую команду, создавая несколько архивов с логами подряд (у эмулятора часто проблемы с сенсорами). Просто отправьте любой из них, остальные проигнорируйте.

Если ваше устройство подключено к Android Studio, логи можно достать напрямую. Для этого откройте в студии вкладку "Device Explorer":

Расположение вкладки "Device Explorer"

Расположение вкладки &quot;Device Explorer&quot;

После этого перейдите в раздел "data/data/your_app_package_name/files/logs/":

Папка "data/data"

Папка &quot;data/data&quot;

Папка "logs"

Папка &quot;logs&quot;

Скопируйте все файлы из папки "logs" и передайте в службу поддержки.

Пример подключения логгера можно посмотреть в демо приложении.

Изменение версии backend api

По умолчанию в мобильном sdk уровень backend api = 15. Вы можете изменить его через поле apiVersion внутри класса ChatTransportConfig, который является дочерним классом ChatConfig. Доступные к изменению версии api - 16, 17, 18, 19, 20

Отключение пользовательского ввода

Для отключения пользовательского ввода и возможности отправки сообщений в чат, необходимо изменить поле userInputEnabled внутри класса ChatConfig

Автоскролл

Если история чата прокручена к более старым сообщениям, в чате появляется кнопка возврата к последним сообщениям и действует следующее поведение:

  • в чате получен TYPING (индикация набора входящего сообщения) = > пользователь остается на текущей позиции истории, ничего не перемещается;
  • в чате получено любое входящее сообщение = > пользователь остается в текущей позиции истории, ничего не перемещается, на кнопке прокрутки появляется индикатор непрочитанных сообщений с указанием количества таких сообщений;
  • пользователь отправил сообщение = > чат прокручивается к последнему сообщению пользователя.

Установка приоритета для канала уведомлений

Начиная с API 26 вы можете устанавливать приоритет для канала уведомлений, подробнее об этом можно почитать здесь: https://developer.android.com/develop/ui/views/notifications/channels . В библиотеке вы можете выставить их через поле notificationImportance: Int (По умолчанию NotificationManager.IMPORTANCE_DEFAULT) при настройке конфига:

ChatConfig(
notificationImportance = NotificationManager.IMPORTANCE_MAX
// ... остальные настройки
)

Настройка перехода по Push-уведомлению

В случае, если пользователь нажал на пуш уведомление библиотеки в области системных уведомлений, будет открыт основной экран библиотеки - ChatActivity. Чтобы изменить данное поведение, можно настроить создание собственного PendingIntent. Рекомендуется использовать данный метод вместо стандартного окна, если вы хотите избежать вероятного задваивания окон чата при клике на уведомление

Для этого воспользуйтесь полем pendingIntentCreator при настройке конфига. Пример:

ChatConfig(
pendingIntentCreator = createPendingIntent(context)
// ... остальные настройки
)

fun createPendingIntent(context: Context?): PendingIntent {
val buttonIntent = Intent(context, YourActivity::class.java)
return PendingIntent.getActivity(
context,
1,
buttonIntent,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
)
}

Конфигурация транспорта (ChatTransportConfig)

Класс ChatTransportConfig описывает параметры подключения мобильного SDK к backend edna Chat Center. Основные поля:

  • baseUrl — базовый URL backend edna Chat Center, через который выполняются REST‑запросы.
  • threadsGateUrl — URL для подключения по WebSocket (real‑time сообщения, индикатор набора и т.п.).
  • datastoreUrl — URL сервиса истории/хранения файлов (datastore).
  • datastoreHeaders: Map<String, String> — дополнительные HTTP‑заголовки для запросов в datastore (например, кастомные заголовки авторизации).
  • apiVersion: Int — версия backend API. По умолчанию используется значение 20, изменять его следует только по рекомендациям технической поддержки.

Пример создания объекта (см. также раздел «Настройка»):

val transportConfig = ChatTransportConfig(
server.serverBaseUrl,
server.threadsGateUrl,
server.datastoreUrl,
hashMapOf(), // datastore headers, если необходимо
apiVersion = apiVersion
)

Конфигурация сети (ChatNetworkConfig)

Класс ChatNetworkConfig объединяет сетевые настройки SDK и используется в поле networkConfig класса ChatConfig. Он состоит из трёх частей:

  • httpConfig: HTTPConfig — настройки HTTP‑клиента (таймауты подключения, чтения/записи и т.п.).
  • wsConfig: WSConfig — настройки WebSocket‑подключения (таймаут подключения, интервалы ping и т.п.).
  • sslPinningConfig: SSLPinningConfig? — параметры SSL pinning (набор доверенных сертификатов, поведение при недоверенном сертификате).

Единицей измерения таймаутов в HTTPConfig и WSConfig являются секунды. Если вы не задаёте свои значения, будут использованы значения по умолчанию, рекомендуемые командой edna.

Для включения SSL pinning используйте пример из раздела про SSL pinning выше, передавая массив сертификатов и флаг allowUntrustedSSLCertificate из конфигурации сервера.

API Reference: ChatCenterUI

Ниже перечислены основные публичные методы класса ChatCenterUI.

Конструктор

  • ChatCenterUI(appContext: Context, logger: ChatLoggerConfig? = null)
    Принимает applicationContext.

Инициализация SDK

  • fun init(providerUid: String, config: ChatConfig)
    Инициализирует SDK без appMarker. Используйте, если на сервере настроено только одно мобильное приложение.

  • fun init(providerUid: String, appMarker: String, config: ChatConfig)
    Полная версия инициализации. providerUid и appMarker вы получаете от поддержки edna. appMarker это уникальный идентификатор приложения на стороне платформы. Он нужен, чтобы отличать одно приложение от другого в рамках одной платформы, правильно маршрутизировать сообщения через Threads Gate, корректно собирать аналитику — app marker используется в отчетах, фильтрах и настройках администратора. Если используется, выдаётся при интеграции или при настройке необходимого функционала (в остальных случаях использовать не нужно).

Оба метода должны вызываться один раз после создания ChatCenterUI и до любых других вызовов SDK (authorize, обработка пушей, получение ChatFragment и т.д.).

Авторизация пользователя

  • fun authorize(client: ChatUser, auth: ChatAuth?)

Назначает текущего пользователя и параметры авторизации. Без вызова authorize(...) сообщения не будут отправляться.

При смене пользователя метод автоматически очищает все данные пользователя

Подробнее о ChatUser и ChatAuth см. раздел «Настройка» → «Авторизация пользователя».

Получение UI-компонентов

  • fun getChatFragment(): ChatFragment?
    Возвращает ChatFragment. Если фрагмент еще не был создан - создаст его. Обычно вызывается из Activity для отображения чата.

  • fun getChatActivity(): ChatActivity?
    Возвращает текущую активность чата, если она открыта. Полезно, если вы используете отдельную Activity для чата и хотите управлять её жизненным циклом.

Если вы хотите больше гибкости при встраивании в свое приложение - используйте метод getChatFragment(). Однако данный подход также требует более внимательного отношения к рекомендациям по интеграции.

Работа с пуш-уведомлениями

  • fun handlePushMessage(bundle: Bundle)
    Обрабатывает входящее push-уведомление в формате Bundle (например, при использовании кастомных приёмников). Метод игнорирует уведомления, не относящиеся к edna Chat Center

  • fun handleFCMMessage(data: Map<String, String>)
    Обрабатывает FCM push в формате data-payload. Обрабатываются только уведомления, содержащие флаг принадлежности к edna Chat Center (origin=threads).

Эти методы предполагают, что SDK уже инициализирован через init(...). Подробнее см. раздел «Уведомления».

Токены пуш-сервисов

Статические методы (используются в FirebaseMessagingService / HmsMessageService):

  • ChatCenterUI.setFCMToken(token: String, context: Context)
  • ChatCenterUI.setHCMToken(token: String, context: Context)

В новой интеграции всегда используйте статические версии с context.

Управление пользователем

  • fun updateUnreadCountMessagesIfNeed()
    Пересчитывает количество непрочитанных сообщений для текущего пользователя, при необходимости запрашивая данные с сервера.

  • fun deauthorizeUser()
    Сбрасывает данные пользователя в SDK без вызова логаута на сервере. Полезно, если вы хотите очистить локальные данные, но оставить сессию на backend-е.

  • fun logout()
    Полный логаут: удаляет данные пользователя в SDK и выполняет разлогинивание на сервере. Рекомендуется вызывать при явном выходе пользователя из аккаунта в вашем приложении.

Работа с сообщениями

  • fun send(message: ChatMessage): Boolean
    Отправляет сообщение от имени текущего авторизованного пользователя. Возвращает true, если сообщение принято в очередь отправки, и false, если пользователь не авторизован или SDK не инициализирован.

Слушатели событий UI

  • fun setChatCenterUIListener(listener: ChatCenterUIListener)
    Позволяет подписаться на события, связанные с UI (открытие/закрытие чата, смена состояния и т.п.). Используется для продвинутых сценариев кастомизации поведения SDK.

Подробности и примеры использования см. в демо-приложении.

Хранение и удаление данных в SDK

  • В SDK данные хранятся только на уровне оперативной памяти (in‑memory) и актуальны до завершения процесса приложения или до явного сброса состояния.
  • После перезапуска приложения состояние SDK восстанавливается только из тех данных, которые предоставляет ваше приложение (например, авторизация пользователя) и ваш backend.

Методы logout() и deauthorizeUser():

  • очищают локальное состояние SDK (данные о текущем пользователе, очереди сообщений, токены авторизации и т.п.);
  • могут использоваться в связке с вашими серверными вызовами для разлогинивания/удаления сессии на backend-е.

Сборка и совместимость зависимостей

Проверка на корректность сборки

Для SDK не требуется дополнительной сборки. Все, что необходимо - это подключить библиотеку через стандартный механизм implementation внутри вашего gradle файла

Совместимость зависимостей

При обновлении зависимостей обратите внимание на возможные конфликты версий:

  • com.google.android.material:material — пример в документации использует 1.13.0, в SDK может использоваться более новая версия;
  • com.google.firebase:firebase-messaging — минимально протестированная версия 23.4.1, при обновлении на более новые версии рекомендуется проверять совместимость;
  • com.squareup.okhttp3:okhttp — версия 4.12.0, рекомендуется периодически проверять наличие известных уязвимостей и при необходимости обновлять.

Рекомендации по безопасности

  • В качестве identifier для ChatUser используйте уникальный, стабильный идентификатор, устойчивый к подбору (например, внутренний UUID пользователя в вашей системе).
  • Не используйте в качестве identifier телефон, email и другие персональные данные в открытом виде.
  • Если вы передаёте идентификатор в зашифрованном виде, обязательно установите флаг isEncrypted = true и используйте надёжную схему шифрования на вашей стороне.
  • Настройку доступности поиска, предпросмотра ссылок и голосовых сообщений выполняйте на стороне сервера, а не через устаревшие клиентские флаги searchEnabled, linkPreviewEnabled, voiceRecordingEnabled.
  • При использовании SSL pinning следите за сроком действия сертификатов и планируйте обновление сертификатов в приложении до истечения их срока.

Troubleshooting (частые проблемы)

Чат не инициализируется / методы SDK бросают исключения

  • Убедитесь, что ChatCenterUI инициализируется один раз в Application.onCreate().
  • Любые вызовы методов SDK должны выполняться после успешной инициализации.
  • При асинхронной инициализации (например, после загрузки конфигурации с сервера) синхронизируйте обработку пуш‑уведомлений с завершением инициализации.

Пуш‑уведомления не открывают чат

  • Проверьте, что токен FCM/HCM передаётся через ChatCenterUI.setFCMToken(...) / setHcmToken(...).
  • Убедитесь, что данные пуша передаются в handleFCMMessage(data) или handlePushMessage(bundle) и содержат флаг принадлежности к edna Chat Center (origin=threads).
  • Проверьте, что корректно настроен pendingIntentCreator в ChatConfig, если вы переопределяете поведение открытия приложения по пушу.

Крэши только в release‑сборке

  • Проверьте настройки ProGuard/R8 и убедитесь, что для зависимостей (Gson, Retrofit, Picasso, WorkManager, FFmpeg, Markwon, JSoup и др.) добавлены необходимые правила.
  • При необходимости обратитесь к демо‑приложению и используемым там правилам shrinker‑а.

Сообщения не доходят, постоянно крутится лоадер где-либо

  • Убедитесь, что устройство имеет доступ в сеть и нет прокси/фильтров, блокирующих WebSocket и/или Rest подключение.
  • Проверьте корректность baseUrl и threadsGateUrl в ChatTransportConfig.
  • Проверьте, что версия backend совместима с версией SDK, указанной в changelog.