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

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

Кастомизация навигации по push

Чтобы изменить поведение при нажатии на push-уведомление (по умолчанию открывается ChatActivity), используйте PendingIntentCreator. См. Настройка перехода по push-уведомлению.

Разрешения

SDK уже объявляет необходимые permissions в своём AndroidManifest.xml (INTERNET, POST_NOTIFICATIONS, WAKE_LOCK, FOREGROUND_SERVICE, ACCESS_NETWORK_STATE). Manifest Merger Android Gradle Plugin корректно объединит их с манифестом вашего приложения — повторно объявлять их не нужно. Полный список — в Разрешения Android (Permissions).

Runtime-permission POST_NOTIFICATIONS на Android 13+ (API 33)

Манифестное объявление само по себе не показывает уведомления. На Android 13+ запросите разрешение через ActivityResultContracts.RequestPermission до того, как пользователь ожидает первый push. Без явного grant система молча дропает уведомления — никакой ошибки в SDK не будет.

// В Activity
val requestPermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { granted ->
if (!granted) {
// покажите rationale или предложите включить уведомления в настройках
}
}

// перед первой подпиской на push
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}

Firebase

Серверная часть настройки FCM

Тот же Firebase-проект, чьим google-services.json пользуется приложение, администратор edna Chat Center заносит в канал на стороне сервера: Sender ID (из настроек Cloud Messaging) и service-account.json (Firebase Console → Project settings → Service accounts → Generate new private key). Если значения в админке не совпадают с локальным google-services.json — тестовый push из Firebase Console приходит, а push от backend edna молча не доставляется. Шаги в админке: Подключение мобильного чата Android.

Во всех примерах ниже chatCenterUI — поле вашего Application / Activity (в примерах используется имя MyApp — замените на имя вашего класса; см. Quick Start → Шаг 1).

Порядок инициализации

ChatCenterUI.setFCMToken(...) / setHCMToken(...) можно вызывать в любой момент — токен сохраняется в Preferences и подхватывается SDK после инициализации.

chatCenterUI.handleFCMMessage(...) / handlePushMessage(...) требуют завершённой инициализации:

  • При init() (синхронный) — гарантируйте, что Application.onCreate завершился до получения первого push.
  • При initAsync() — отложите вызов handleFCMMessage до колбэка onInitComplete, иначе push-сообщение будет потеряно. См. Асинхронная инициализация: initAsync().

Шаг 1. Создайте FirebaseMessagingService

Создайте подкласс FirebaseMessagingService, передающий токен и сообщения в SDK:

class CustomPushFcmIntentService : FirebaseMessagingService() {

override fun onNewToken(token: String) {
super.onNewToken(token)
ChatCenterUI.setFCMToken(token, applicationContext)
}

override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
val chatCenterUI = (application as MyApp).chatCenterUI
chatCenterUI.handleFCMMessage(message.data)
}
}

handleFCMMessage(data) принимает Map<String, String> и обрабатывает только push с флагом origin=threads — остальные тихо игнорирует. Альтернатива — handlePushMessage(bundle: Bundle) с тем же фильтром.

Что лежит в message.data

Состав payload определяется серверной настройкой шаблона push в админке edna Chat Center. Стандартные поля (origin=threads, идентификаторы сообщения, текст-превью) SDK обрабатывает сам; дополнительные ключи из шаблона приходят как строки (вложенные объекты сериализуются админкой в JSON-строку перед отправкой на Android). Подробнее — Настройка шаблонов пуш-уведомлений.

Сосуществование с другим FirebaseMessagingService

Android разрешает только один сервис с intent-фильтром com.google.firebase.MESSAGING_EVENT. Если у вас уже есть свой сервис (например, для Firebase Analytics или другого push-источника), не добавляйте второй — добавьте проксирование edna в существующий:

override fun onNewToken(token: String) {
super.onNewToken(token)
// ... ваш существующий код ...
ChatCenterUI.setFCMToken(token, applicationContext)
}

override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
val chatCenterUI = (application as MyApp).chatCenterUI
if (message.data["origin"] == "threads") {
chatCenterUI.handleFCMMessage(message.data)
} else {
// ваш обработчик не-edna push
}
}

Шаг 2. Подключите google-services.json

Возможны два варианта:

  • Используя ваш аккаунт Firebase. Сформируйте google-services.json в консоли Firebase. Администратору edna Chat Center передайте два значения этого же Firebase-проекта:

    • Sender ID — из Firebase Console → Project settings → Cloud Messaging;
    • service-account.json — из Firebase Console → Project settings → Service accounts → Generate new private key.

    Администратор заносит их в канал на вкладке «Уведомления» — пошаговая инструкция: Подключение мобильного чата Android.

  • Используя аккаунт Firebase edna. Сообщите applicationId вашего приложения — в ответ получите google-services.json.

google-services.json добавьте в корень модуля приложения (рядом с build.gradle). applicationId модуля должен совпадать с полем App_package в канале admin-панели edna.

Шаг 3. Зарегистрируйте сервис в манифесте

<service android:name=".push.CustomPushFcmIntentService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

Канал уведомлений (Android 8+)

SDK создаёт канал уведомлений автоматически на Android 8.0+. Приоритет канала настраивается через ChatConfig.notificationImportance (по умолчанию IMPORTANCE_DEFAULT). Поле помечено @RequiresApi(N) — если minSdk приложения ниже 24, оборачивайте установку значения в проверку Build.VERSION.SDK_INT >= Build.VERSION_CODES.N. Полная таблица значений и нюансы — в Advanced → Установка приоритета для канала уведомлений.

Logout и токен

При logout() SDK очищает локально сохранённый FCM/HCM-токен. В multi-account сценарии после следующей авторизации заново передайте токен в SDK через ChatCenterUI.setFCMToken(...) / setHCMToken(...).

Huawei Mobile Services (HMS)

Для устройств Huawei без Google Play Services используйте HMS Push Kit.

Канал Huawei в админке

Перед интеграцией убедитесь, что в edna Chat Center заведён отдельный канал типа «Мобильный чат → Huawei». В канале заполняется App_package (= applicationId модуля Huawei-сборки), а на вкладке «Уведомления» — Huawei App ID и Huawei App Secret (это OAuth 2.0 Client ID и Client secret из AppGallery Connect → Project settings → App information, не Push Kit App ID). Шаги в админке: Подключение мобильного чата Huawei.

Шаг 1. Добавьте зависимости HMS

implementation 'com.huawei.hms:push:6.11.0.300'

Также добавьте плагин com.huawei.agconnect в build.gradle и файл agconnect-services.json в модуль app/.

Где взять credentials для Huawei
  • agconnect-services.json — из AppGallery Connect → Project settings → App information → секция agconnect-services.json.
  • Huawei App ID и Huawei App Secret для админки edna — там же, в секции OAuth 2.0 Client ID (поля Client ID и Client secret).

Если после пересоздания OAuth-ключей в AppGallery Connect значения в админке edna не обновлены, backend перестаёт авторизоваться в HMS Push Kit, и push не приходят без явной ошибки в логах. См. Подключение мобильного чата Huawei.

Шаг 2. Создайте сервис обработки push-уведомлений

import android.os.Bundle
import android.util.Base64
import com.huawei.hms.push.HmsMessageService
import com.huawei.hms.push.RemoteMessage
import edna.chatcenter.ui.visual.core.ChatCenterUI
import org.json.JSONObject

class CustomPushHcmIntentService : HmsMessageService() {

override fun onNewToken(token: String) {
super.onNewToken(token)
ChatCenterUI.setHCMToken(token, applicationContext)
}

override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
val chatCenterUI = (application as MyApp).chatCenterUI
chatCenterUI.handlePushMessage(base64JsonStringToBundle(message.data))
}

private fun base64JsonStringToBundle(base64Str: String): Bundle = try {
val json = JSONObject(String(Base64.decode(base64Str, 0)))
Bundle().apply {
json.keys().forEach { key -> putString(key, json.getString(key)) }
}
} catch (_: Exception) {
Bundle()
}
}

HMS отдаёт payload в RemoteMessage.data как base64-строку (JSON-объект внутри), поэтому перед передачей в SDK её нужно декодировать в Bundle и использовать handlePushMessage(bundle), а не handleFCMMessage(map).

Шаг 3. Зарегистрируйте сервис в AndroidManifest.xml

<service android:name=".push.CustomPushHcmIntentService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
</intent-filter>
</service>

Шаг 4. Запросите токен при инициализации

При старте приложения запросите HMS-токен:

import com.huawei.agconnect.AGConnectOptionsBuilder
import com.huawei.hms.aaid.HmsInstanceId
import com.huawei.hms.common.ApiException

fun requestHmsToken(context: Context) {
Thread {
try {
val appId = AGConnectOptionsBuilder().build(context).getString("client/app_id")
val token = HmsInstanceId.getInstance(context).getToken(appId, "HCM")
if (!token.isNullOrEmpty()) {
ChatCenterUI.setHCMToken(token, context)
}
} catch (e: ApiException) {
Log.e("HMS", "Token request failed", e)
}
}.start()
}

appId берётся из agconnect-services.json через AGConnectOptionsBuilder — не нужно хардкодить значение в коде.

Полный пример интеграции HMS доступен в демо-приложении.

Проверка интеграции

  1. Тестовый push приходит.

    • FCM: Firebase Console → Cloud MessagingSend test message, в разделе Additional options → Custom data добавьте ключ origin со значением threads.
    • HMS: AppGallery Connect → Push KitAdd notification → секция Custom message с парой origin=threads.

    Без пары origin=threads SDK проигнорирует push. Если в production нужно передавать дополнительные поля в payload (например, externalId сообщения для дип-линка) — настройка делается на стороне сервера через шаблон push: Настройка шаблонов пуш-уведомлений. Кастомные поля доступны из message.data до вызова handleFCMMessage(...) либо могут читаться вашим PendingIntentCreator.

  2. Уведомление видно на устройстве (Android 13+). Если push приходит, но баннер не появляется — проверьте, что runtime-разрешение POST_NOTIFICATIONS выдано пользователем (см. предупреждение в разделе Разрешения).

  3. Порядок инициализации соблюдён. Если первый push после холодного старта теряется — ChatCenterUI.init(...) не завершился до вызова handleFCMMessage(...). См. Асинхронная инициализация.