Как подключить Firebase Cloud Messaging в Android-приложении на Kotlin

Первый тест FCM должен отвечать на простой вопрос: зарегистрировалось ли конкретное приложение и появилось ли у него тестовое уведомление? Для этого достаточно Android-проекта, Firebase Console и устройства. Сервер массовой рассылки, пользовательские сегменты и маркетинговая аналитика на этом этапе только усложняют диагностику.
Ниже — учебная интеграция на Kotlin с обычным SDK и совместимым сценарием registration token. В документации Firebase на ноябрь 2026 года доступ к этому токену уже помечен deprecated; предлагается Firebase Installation ID и callback onRegistered. При этом официальный тест из Console ещё описан через поле FCM registration token. Поэтому здесь показан именно этот ограниченный совместимый тест, а не рекомендуемая архитектура нового сервера на годы.
Не смешивайте две модели получения сообщений
Официальная документация отдельно описывает AndroidConfigV2 как preview. У него свои callbacks и автоматический показ уведомлений, в том числе в foreground. Таблица foreground/background ниже относится к прежним сообщениям AndroidConfig, которые документация называет legacy. Не переносите её на V2 и не добавляйте экспериментальные callbacks в обычный проект по одному фрагменту чужой инструкции.
FCM подходит для уведомления о событии и сигнала приложению обновить данные. Важные данные должны оставаться доступны через обычный интерфейс приложения: появление push не заменяет проверку состояния заказа или сообщения. В учебном примере будет только текст «Проверка связи», без персональных данных и обещаний гарантированного времени доставки.
Зарегистрируйте правильное Android-приложение
- Создайте или выберите проект в Firebase Console и добавьте Android-приложение.
- Укажите package name фактической сборки — applicationId модуля приложения. Сверяйте конкретный вариант сборки: суффикс debug может менять идентификатор. Не ориентируйтесь только на имя Kotlin-пакета файла.
- Зарегистрируйте приложение, скачайте google-services.json и положите его в корень app-модуля, рядом с его Gradle-файлом.
- Проверьте точное имя: google-services (2).json не является требуемым именем конфигурационного файла.
В авторском примере applicationId — com.example.pushdemo. Если Firebase зарегистрирован как com.example.pushdemo, а установлен вариант com.example.pushdemo.debug, сначала исправьте соответствие регистрации и конфигурации. Бессмысленно искать эту ошибку в обработчике уведомлений.
Файл Firebase содержит идентификаторы проекта и приложения, а не серверный ключ отправки. Не добавляйте service account JSON или серверные полномочия в APK. Для описанного Console-теста не нужно придумывать SHA-отпечаток как универсальное условие FCM: другие продукты Firebase могут иметь собственные требования, но это отдельная настройка.
Подключите плагин и библиотеку
Сохраните совместимые с вашим проектом версии Android Gradle Plugin и Kotlin. В корневом Gradle-файле объявите Google services plugin, а в app-модуле примените его. Показанные версии Google-плагина и BoM взяты из страницы настройки Firebase на момент подготовки; перед обновлением существующего проекта сопоставьте их с его зависимостями.
// Корневой build.gradle.kts, внутри plugins
id("com.google.gms.google-services") version "4.5.0" apply false
// app/build.gradle.kts
plugins {
id("com.android.application")
id("com.google.gms.google-services")
}
dependencies {
implementation(platform("com.google.firebase:firebase-bom:35.1.0"))
implementation("com.google.firebase:firebase-messaging")
}
Это вставки в существующий проект, не полный Gradle-файл с настройками Android и Kotlin. BoM согласует версии библиотек Firebase; у firebase-messaging отдельную версию здесь не задают. Выполните Gradle Sync, затем сборку. Пока зависимость не разрешилась, проверка push преждевременна. Analytics рекомендуется Firebase и требуется для отчётности о доставке, но не является обязательной библиотекой самого минимального теста получения.
Зарегистрируйте сервис и получите токен тестового экземпляра
Создайте класс в пакете приложения. Минимальный учебный сервис фиксирует обновление токена и приём сообщения, но самостоятельно уведомление не рисует:
import android.util.Log
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
class PushService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
Log.d("PushDemo", "Test token: $token")
}
override fun onMessageReceived(message: RemoteMessage) {
Log.d("PushDemo", "Message received: ${message.messageId}")
}
}
Внутри application в AndroidManifest.xml зарегистрируйте именно свой класс:
<service android:name=".PushService" android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Для получения уже существующего токена, а не только ожидания его обновления, вызовите из Activity:
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
Log.d("PushDemo", "Test token: ${task.result}")
} else {
Log.w("PushDemo", "Token request failed", task.exception)
}
}
Нужны импорты FirebaseMessaging и Log. Логирование токена оставлено только как инструмент локального теста; уберите его из рабочего варианта. Токен относится к экземпляру приложения, меняется, например, после переустановки или очистки данных. Сохранённый вчера токен нельзя считать вечным. В серверной интеграции обновление нужно передавать и учитывать на сервере; здесь сервер не создаётся.
Разрешение, канал и состояние приложения
На Android 13 и выше для обычного показа уведомлений нужно runtime-разрешение POST_NOTIFICATIONS. Одного объявления в manifest недостаточно. SDK FCM включает объявление начиная с указанной в документации версии 23.0.6, но приложение всё равно запрашивает разрешение у пользователя, например через Activity Result API. Объясните назначение запроса и обработайте отказ; отсутствие разрешения не исправляется повторной отправкой того же push.
Если приложение самостоятельно создаёт уведомления, на Android 8.0 и выше требуется канал уведомлений. Это отдельная сущность от runtime-разрешения. Для первого теста ниже используется фоновое notification-сообщение и стандартное отображение SDK; полноценный собственный NotificationCompat.Builder в пример не включён.
| Legacy-сообщение | Приложение открыто | Приложение в фоне |
|---|---|---|
| Notification | onMessageReceived; наш сервис только пишет событие | Показ в системной области уведомлений |
| Data | onMessageReceived | onMessageReceived с учётом ограничений доставки и выполнения |
| Notification + data | onMessageReceived | Уведомление показывается; данные передаются в extras запускаемого Intent после нажатия |
В foreground приём в нашем сервисе не означает появление баннера: собственный показ не реализован. Не выполняйте долгую загрузку внутри onMessageReceived — документация предупреждает о коротком окне обработки. Продолжительную задачу проектируют отдельно.
Отправьте тест из Console и локализуйте сбой
Установите и запустите приложение на совместимом устройстве с Google Play services, разрешите уведомления и получите свежий токен. Переведите приложение в фон обычной кнопкой Home. В Firebase Console откройте DevOps & Engagement → Messaging, создайте notification campaign, введите тестовый текст и выберите Send test message. В поле Add an FCM registration token вставьте токен этого экземпляра и нажмите Test.
Для авторской проверки сравните два опыта: сначала фоновое приложение и уведомление в системной области, затем открытое приложение и запись Message received. Это ожидаемые результаты описанной legacy-схемы, не отчёт о фактически выполненном здесь запуске Android-проекта.
- Не собирается проект: разберите Gradle, плагин и расположение JSON раньше сети FCM.
- Нет токена: прочитайте exception, проверьте сеть, регистрацию приложения и Google Play services.
- Токен есть, показа нет: проверьте разрешение, системные настройки уведомлений, состояние приложения и свежесть токена.
- В фоне нет callback для notification: это ожидаемый маршрут таблицы, а не доказательство поломки сервиса.
- Поменялось поведение после перехода на V2: сверяйте модель сообщения и соответствующие callbacks, а не добавляйте повторный показ вслепую.
Первый законченный результат — воспроизводимый тест конкретной сборки с известным токеном и понятным поведением в двух состояниях. Следующий шаг — отдельно спроектировать актуальную регистрацию, серверную отправку и обработку данных, сохранив этот тест как контроль интеграции.



