Вы когда-нибудь задумывались, как смартфоны получают и обрабатывают уведомления приложений в разных состояниях: открыто/закрыто/в фоновом режиме?

Firebase Cloud Messaging  —  это кроссплатформенный инструмент для отправки push-уведомлений на одно или несколько устройств. Мгновенные сообщения могут передать полезную нагрузку в приложение клиента размером до 4 кб.


Теперь давайте применим FCM в проекте, запущенном в Android Studio.

Создание проекта Firebase

Откройте консоль Firebase, нажмите Add Project и следуйте шагам для настройки проекта (также можете воспользоваться этой инструкцией “Добавьте Firebase в свой проект Android”).

Затем добавьте приложение в созданный проект.

Введите название проекта, название пакета и ключ SHA-1 от проекта в Android Studio. Следуйте инструкции, чтобы завершить подключение приложения к Firebase. 

Готово. Вы подключили Firebase к проекту Android. Теперь добавим Firebase SDK в проект для работы с FCM.


Добавление Firebase SDK

Шаг 1: добавьте код ниже в файл <project>/build.gradle:

buildscript {
dependencies {
// Добавьте строку
classpath 'com.google.gms:google-services:4.3.2'
}
}

Шаг 2: добавьте код ниже в <project>/<app>/build.gradle:

dependencies {
// Добавьте строку
implementation 'com.google.firebase:firebase-messaging:20.0.0'
}
...
// Добавьте в конец этого файла
apply plugin: 'com.google.gms.google-services'

Шаг 3: нажмите Sync Now для синхронизации изменений в gradle.


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

  1. На одно устройство: для этого нужен регистрационный токен приложения клиента, который генерируется при помощи Firebase SDK. Имейте в виду, что этот токен динамический и будет регулярно меняться.

Получить текущий токен можно так:

FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
@Override
public void onComplete(@NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "getInstanceId failed",
task.getException());
return;
}

// Новый ID токена
String token = task.getResult().getToken();
}
});

2. На несколько устройств: для этого все устройства должны подписаться на общую тему “xyz”.

Вставьте следующий код в Activity, чтобы подписаться или отписаться:

Subscribe Topic :
FirebaseMessaging.getInstance().subscribeToTopic("TopicName");
Unsubscribe Topic : FirebaseMessaging.getInstance().unsubscribeFromTopic("TopicName");

Типы сообщений Firebase

  1. Уведомления: такие сообщения нельзя кастомизировать. У них есть только два ключевых значения: title и body.
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
}
}
}

2. Данные: сообщения с данными обрабатываются приложением Android. Они подходят для отправки сообщений, включающих данные. Их можно кастомизировать в паре ключ-значение:

{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data":{
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}
}

3. Гибрид из двух вышеуказанных: сообщение может содержать уведомления с данными. Такие сообщения обрабатываются двумя сценариями в зависимости от состояния приложения (работа в фоновом режиме/открыто). Используем ключи уведомлений и данных:

{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"title":"Portugal vs. Denmark",
"body":"great match!"
},
"data" : {
"Nick" : "Mario",
"Room" : "PortugalVSDenmark"
}
}
}

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

Как сказано выше, сообщения FCM будут обрабатываться по-разному в зависимости от типа полезной нагрузки и состояния приложения.

Обработка уведомлений:

Если приложение работает в фоновом режиме, система сама автоматически обрабатывает уведомление и выводит его на экран без открытия приложения.

Если приложение открыто, то необходимо вызвать функцию onMessageReceived. Для этого создайте класс Java MyFirebaseMessagingService, расширяющий FirebaseMessagingService.

Объявите действие в качестве службы в App Manifest:

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

Напишите следующий код в MyFirebaseMessagingService для функции onMessageReceived:

@Override
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(remoteMessage);
}
private void sendNotification(RemoteMessage remoteMessage) {
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent =PendingIntent.getActivity(this,
m,intent,PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder;
notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.geekhaven_transparent)
.setContentTitle(remoteMessage.getNotification.getTitle)
.setContentText(remoteMessage.getNotification.getBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

// Необходим канал уведомлений Android Oreo
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(m, notificationBuilder.build());

Для отправки уведомлений с полезной нагрузкой измените две следующие строки:

вместо:

.setContentTitle(remoteMessage.getNotification.getTitle)
.setContentText(remoteMessage.getNotification.getBody)

пишем:

.setContentTitle(remoteMessage.getData.get("your_key1")
.setContentText(remoteMessage.getData.get("your_key2")

Если вы отправляете уведомления с бэкенда, то необходимо отправлять регистрационный токен каждый раз, когда он меняется. Для этого посмотрите на метод onNewToken в MyMessagingService.

Как выбрать полезную нагрузку?

Выбор зависит от вашей цели. Например, если нужно отправить в уведомлении только заголовок и тело, то выбираем уведомления. Если нужно отправить больше информации или кастомизировать уведомление, добавив действия, то выбираем отправку данных. Такие уведомления всегда попадают в метод onMessageReceived независимо от того, в каком состоянии находится приложение.

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

Как отправить FCM сообщение вручную?

Отправлять уведомления можно из консоли Firebase: Firebase Console — →Grow — →Cloud Messaging:

Нажмите на Send your first message, заполните заголовок и тело.

Если хотите отправить уведомление на определенное устройство, нажмите на Send test message и введите текущий регистрационный токен.

Нажмите Test.

Если хотите отправить уведомление, используя тему, нажмите на next, выберите текущее приложение и введите тему.

Нажмите на Publish.

А вот и уведомление:


Отправить данные или гибрид вручную через Firebase нельзя, так как для этого еще нет инструмента, но для этих случаев можно скачать или добавить расширение POSTMAN.

Отправка данных по протоколу HTTP с помощью POSTMAN

Шаг 1. Выберите POST. Введите запрос URL: https://fcm.googleapis.com/fcm/send

Шаг 2. Добавьте заголовки Authorization: key=<server_key> и Content-Type: application/json.

Как получить Server_key?

Откройте консоль Firebase — →Project Settings — →Cloud Messaging.

Для отправки сообщения выберите Body — →Raw — →JSON(application/json).

{
"to" : "YOUR_FCM_TOKEN",
"data" : {
"body" : "Notification Body",
"title": "Notification Title",
"key_1" : "Value for key_1",
"key_2" : "Value for key_2"
}
}

С помощью POSTMAN можно отправлять и уведомления. Для всех трех типов используйте следующий код:

{
"to" : "YOUR_FCM_TOKEN",
"notification" : {
"body" : "Body of Your Notification",
"title": "Title of Your Notification"
},
"data" : {
"body" : "Notification Body",
"title": "Notification Title",
"key_1" : "Value for key_1",
"key_2" : "Value for key_2"
}
}

Чтобы отправить уведомление на несколько устройств используйте registration_ids или "to":"topic/topic_name" вместо to.

Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи VARUN BHARDWAJ: Sending Push Notifications by Using Firebase Cloud Messaging

Предыдущая статьяПовторный рендеринг и мемоизация в React
Следующая статьяКак оставаться на гребне волны в океане современных веб-разработок