Firebase Cloud Messaging предоставляет два способа нацеливания сообщения на несколько устройств:
- Тематические сообщения , которые позволяют отправлять сообщения на несколько устройств, которые выбрали определенную тему.
- Обмен сообщениями группы устройств , который позволяет отправлять сообщения на несколько устройств, принадлежащих определенной вами группе.
В этом руководстве основное внимание уделяется отправке тематических сообщений с вашего сервера приложений с помощью Admin SDK или REST API для FCM, а также их получению и обработке в приложении для Android. Мы рассмотрим обработку сообщений как для фоновых, так и для приоритетных приложений. Охвачены все шаги для достижения этого, от настройки до проверки.
Настройте SDK
В этом разделе могут быть описаны шаги, которые вы уже выполнили, если вы настроили клиентское приложение Android для FCM или выполнили шаги для отправки первого сообщения .
Прежде чем вы начнете
Установите или обновите Android Studio до последней версии.
Убедитесь, что ваш проект соответствует следующим требованиям:
- Ориентирован на уровень API 19 (KitKat) или выше.
- Использует Android 4.4 или выше
- Использует Jetpack (AndroidX) , который включает в себя выполнение следующих требований к версии:
-
com.android.tools.build:gradle
v3.2.1 или новее -
compileSdkVersion
28 или новее
-
Настройте физическое устройство или используйте эмулятор для запуска приложения.
Обратите внимание, что Firebase SDK с зависимостью от сервисов Google Play требует, чтобы на устройстве или эмуляторе были установлены сервисы Google Play.Войдите в Firebase , используя свою учетную запись Google.
Если у вас еще нет проекта Android и вы просто хотите попробовать продукт Firebase, вы можете загрузить один из наших кратких примеров .
Создайте проект Firebase
Прежде чем вы сможете добавить Firebase в свое Android-приложение, вам необходимо создать проект Firebase для подключения к вашему Android-приложению. Посетите страницу Understand Firebase Projects , чтобы узнать больше о проектах Firebase.
Зарегистрируйте свое приложение в Firebase
Чтобы использовать Firebase в своем приложении для Android, вам необходимо зарегистрировать свое приложение в проекте Firebase. Регистрация вашего приложения часто называется «добавлением» вашего приложения в ваш проект.
Перейдите в консоль Firebase .
В центре страницы обзора проекта щелкните значок Android (
) или «Добавить приложение» , чтобы запустить рабочий процесс установки.Введите имя пакета вашего приложения в поле имени пакета Android .
Имя пакета однозначно идентифицирует ваше приложение на устройстве и в магазине Google Play.
Имя пакета часто называют идентификатором приложения .
Найдите имя пакета вашего приложения в файле Gradle вашего модуля (уровня приложения), обычно
app/build.gradle
(пример имени пакета:com.yourcompany.yourproject
).Имейте в виду, что значение имени пакета чувствительно к регистру, и его нельзя изменить для этого приложения Firebase для Android после его регистрации в вашем проекте Firebase.
(Необязательно) Введите другую информацию о приложении: псевдоним приложения и сертификат подписи отладки SHA-1 .
Псевдоним приложения . Внутренний удобный идентификатор, который виден только вам в консоли Firebase.
Сертификат подписи отладки SHA-1 : хэш SHA-1 требуется для аутентификации Firebase (при использовании входа через Google или номера телефона ) и динамических ссылок Firebase .
Щелкните Зарегистрировать приложение .
Добавьте файл конфигурации Firebase
Загрузите и добавьте файл конфигурации Firebase Android (
) в свое приложение:google-services.json Нажмите Загрузить google-services.json , чтобы получить файл конфигурации Firebase Android.
Переместите файл конфигурации в корневой каталог модуля (уровня приложения) вашего приложения.
Файл конфигурации Firebase содержит уникальные, но не секретные идентификаторы вашего проекта. Чтобы узнать больше об этом конфигурационном файле, посетите страницу Understand Firebase Projects .
Вы можете снова загрузить файл конфигурации Firebase в любое время.
Убедитесь, что к имени файла конфигурации не добавляются дополнительные символы, например
(2)
.
Чтобы сделать значения в вашем файле конфигурации
доступными для SDK Firebase, вам нужен подключаемый модуль Gradle сервисов Google (google-services.json google-services
).В файле Gradle корневого уровня (уровня проекта) (
<project>/build.gradle
) добавьте плагин сервисов Google в качестве зависимости buildscript:buildscript { repositories { // Make sure that you have the following two repositories google() // Google's Maven repository mavenCentral() // Maven Central repository } dependencies { ... // Add the dependency for the Google services Gradle plugin classpath 'com.google.gms:google-services:4.3.15' } } allprojects { ... repositories { // Make sure that you have the following two repositories google() // Google's Maven repository mavenCentral() // Maven Central repository } }
В файле Gradle вашего модуля (уровня приложения) (обычно
<project>/<app-module>/build.gradle
) добавьте плагин сервисов Google:plugins { id 'com.android.application' // Add the Google services Gradle plugin id 'com.google.gms.google-services' ... }
Добавьте Firebase SDK в свое приложение
В файле Gradle вашего модуля (на уровне приложения) (обычно
<project>/<app-module>/build.gradle
) добавьте зависимость для библиотеки Android Firebase Cloud Messaging. Мы рекомендуем использовать Firebase Android BoM для управления версиями библиотеки.Для оптимальной работы с Firebase Cloud Messaging мы рекомендуем включить Google Analytics в вашем проекте Firebase и добавить Firebase SDK для Google Analytics в ваше приложение.
Java
dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:32.1.0') // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries // When using the BoM, you don't specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-messaging' implementation 'com.google.firebase:firebase-analytics' }
Используя Firebase Android BoM , ваше приложение всегда будет использовать совместимые версии библиотек Firebase Android.
(Альтернатива) Добавить зависимости библиотеки Firebase без использования BoM
Если вы решите не использовать Firebase BoM, вы должны указать каждую версию библиотеки Firebase в строке зависимостей.
Обратите внимание: если вы используете несколько библиотек Firebase в своем приложении, мы настоятельно рекомендуем использовать BoM для управления версиями библиотек, что гарантирует совместимость всех версий.
dependencies { // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-messaging:23.1.2' implementation 'com.google.firebase:firebase-analytics:21.3.0' }
Kotlin+KTX
dependencies { // Import the BoM for the Firebase platform implementation platform('com.google.firebase:firebase-bom:32.1.0') // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries // When using the BoM, you don't specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-messaging-ktx' implementation 'com.google.firebase:firebase-analytics-ktx' }
Используя Firebase Android BoM , ваше приложение всегда будет использовать совместимые версии библиотек Firebase Android.
(Альтернатива) Добавить зависимости библиотеки Firebase без использования BoM
Если вы решите не использовать Firebase BoM, вы должны указать каждую версию библиотеки Firebase в строке зависимостей.
Обратите внимание: если вы используете несколько библиотек Firebase в своем приложении, мы настоятельно рекомендуем использовать BoM для управления версиями библиотек, что гарантирует совместимость всех версий.
dependencies { // Add the dependencies for the Firebase Cloud Messaging and Analytics libraries // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation 'com.google.firebase:firebase-messaging-ktx:23.1.2' implementation 'com.google.firebase:firebase-analytics-ktx:21.3.0' }
Синхронизируйте свой проект Android с файлами Gradle.
Сборки Gradle, использующие подключаемый модуль Android Gradle (AGP) версии 4.2 или более ранней, должны включать поддержку Java 8. В противном случае эти проекты Android получат ошибку сборки при добавлении Firebase SDK.
Чтобы исправить эту ошибку сборки, вы можете воспользоваться одним из двух вариантов:
- Добавьте перечисленные
compileOptions
из сообщения об ошибке в файлbuild.gradle
уровня приложения . - Увеличьте
minSdkVersion
для вашего проекта Android до 26 или выше.
Узнайте больше об этом сбое сборки в этом FAQ .
- Добавьте перечисленные
Подпишите клиентское приложение на тему
Клиентские приложения могут подписаться на любую существующую тему или создать новую тему. Когда клиентское приложение подписывается на новую тему (которая еще не существует для вашего проекта Firebase), в FCM создается новая тема с таким именем, и впоследствии любой клиент может подписаться на нее.
Чтобы подписаться на тему, клиентское приложение вызывает Firebase Cloud Messaging subscribeToTopic()
с именем темы FCM. Этот метод возвращает Task
, который может использоваться прослушивателем завершения, чтобы определить, прошла ли подписка успешно:
Kotlin+KTX
Firebase.messaging.subscribeToTopic("weather") .addOnCompleteListener { task -> var msg = "Subscribed" if (!task.isSuccessful) { msg = "Subscribe failed" } Log.d(TAG, msg) Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show() }
Java
FirebaseMessaging.getInstance().subscribeToTopic("weather") .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { String msg = "Subscribed"; if (!task.isSuccessful()) { msg = "Subscribe failed"; } Log.d(TAG, msg); Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show(); } });
Чтобы отказаться от подписки, клиентское приложение вызывает Firebase Cloud Messaging unsubscribeFromTopic()
с названием темы.
Получение и обработка тематических сообщений
FCM доставляет тематические сообщения так же, как и другие нижестоящие сообщения.
Для получения сообщений используйте службу, которая расширяет FirebaseMessagingService . Ваша служба должна переопределять обратные вызовы onMessageReceived
и onDeletedMessages
. Он должен обрабатывать любое сообщение в течение 20 секунд после получения (10 секунд на Android Marshmallow). Временное окно может быть короче в зависимости от задержек операционной системы перед вызовом onMessageReceived
. По истечении этого времени различные варианты поведения ОС, такие как ограничения фонового выполнения Android O, могут помешать вам завершить работу. Для получения дополнительной информации см. наш обзор приоритета сообщения .
onMessageReceived
предоставляется для большинства типов сообщений, за следующими исключениями:
Уведомления доставляются, когда ваше приложение находится в фоновом режиме . В этом случае уведомление доставляется в системный трей устройства. Пользователь, нажимающий на уведомление, по умолчанию открывает панель запуска приложений.
Сообщения с уведомлением и полезными данными при получении в фоновом режиме . В этом случае уведомление доставляется в системный трей устройства, а полезная нагрузка данных доставляется в дополнение к намерению вашей активности запуска.
В итоге:
Состояние приложения | Уведомление | Данные | Оба |
---|---|---|---|
Передний план | onMessageReceived | onMessageReceived | onMessageReceived |
Фон | Системный трей | onMessageReceived | Уведомление: системный трей Данные: в статистах умысла. |
Изменить манифест приложения
Чтобы использовать FirebaseMessagingService
, необходимо добавить в манифест приложения следующее:
<service android:name=".java.MyFirebaseMessagingService" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
Кроме того, рекомендуется установить значения по умолчанию, чтобы настроить внешний вид уведомлений. Вы можете указать настраиваемый значок по умолчанию и настраиваемый цвет по умолчанию, которые применяются всякий раз, когда эквивалентные значения не установлены в полезной нагрузке уведомления.
Добавьте эти строки внутри тега application
, чтобы установить пользовательский значок по умолчанию и пользовательский цвет:
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages. See README(https://goo.gl/l4GJaQ) for more. --> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_stat_ic_notification" /> <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming notification message. See README(https://goo.gl/6BKBk7) for more. --> <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" />
Android отображает пользовательский значок по умолчанию для
- Все уведомления, отправленные из Notifications composer .
- Любое сообщение уведомления, которое явно не устанавливает значок в полезной нагрузке уведомления.
Android использует пользовательский цвет по умолчанию для
- Все уведомления, отправленные из Notifications composer .
- Любое сообщение уведомления, в котором явно не задан цвет полезных данных уведомления.
Если не задан пользовательский значок по умолчанию и не задан значок в полезной нагрузке уведомления, Android отображает значок приложения, окрашенный в белый цвет.
Переопределить onMessageReceived
Переопределив метод FirebaseMessagingService.onMessageReceived
, вы можете выполнять действия на основе полученного объекта RemoteMessage и получать данные сообщения:
Kotlin+KTX
override fun onMessageReceived(remoteMessage: RemoteMessage) { // TODO(developer): Handle FCM messages here. // Not getting messages here? See why this may be: https://goo.gl/39bRNJ Log.d(TAG, "From: ${remoteMessage.from}") // Check if message contains a data payload. if (remoteMessage.data.isNotEmpty()) { Log.d(TAG, "Message data payload: ${remoteMessage.data}") // Check if data needs to be processed by long running job if (needsToBeScheduled()) { // For long-running tasks (10 seconds or more) use WorkManager. scheduleJob() } else { // Handle message within 10 seconds handleNow() } } // Check if message contains a notification payload. remoteMessage.notification?.let { Log.d(TAG, "Message Notification Body: ${it.body}") } // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. See sendNotification method below. }
Java
@Override public void onMessageReceived(RemoteMessage remoteMessage) { // TODO(developer): Handle FCM messages here. // Not getting messages here? See why this may be: https://goo.gl/39bRNJ Log.d(TAG, "From: " + remoteMessage.getFrom()); // Check if message contains a data payload. if (remoteMessage.getData().size() > 0) { Log.d(TAG, "Message data payload: " + remoteMessage.getData()); if (/* Check if data needs to be processed by long running job */ true) { // For long-running tasks (10 seconds or more) use WorkManager. scheduleJob(); } else { // Handle message within 10 seconds handleNow(); } } // Check if message contains a notification payload. if (remoteMessage.getNotification() != null) { Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody()); } // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. See sendNotification method below. }
Переопределить onDeletedMessages
В некоторых ситуациях FCM может не доставить сообщение. Это происходит, когда слишком много сообщений (> 100) ожидают вашего приложения на определенном устройстве во время его подключения или если устройство не подключалось к FCM более одного месяца. В этих случаях вы можете получить обратный вызов FirebaseMessagingService.onDeletedMessages()
. Когда экземпляр приложения получает этот обратный вызов, он должен выполнить полную синхронизацию с вашим сервером приложений. Если вы не отправляли сообщение в приложение на этом устройстве в течение последних 4 недель, FCM не будет вызывать onDeletedMessages()
.Обработка уведомлений в фоновом приложении
Когда ваше приложение работает в фоновом режиме, Android направляет уведомления на панель задач. Пользователь, нажав на уведомление, по умолчанию открывает панель запуска приложений.
Сюда входят сообщения, содержащие как уведомления, так и полезные данные (и все сообщения, отправленные из консоли уведомлений). В этих случаях уведомление доставляется в системный трей устройства, а полезная нагрузка данных доставляется в дополнительных целях вашего действия запуска.
Чтобы получить представление о доставке сообщений в ваше приложение, см. информационную панель отчетности FCM , которая записывает количество сообщений, отправленных и открытых на устройствах Apple и Android, а также данные о «показах» (уведомлениях, просмотренных пользователями) для приложений Android.
Создание запросов на отправку
После того, как вы создали тему, либо подписав экземпляры клиентского приложения на тему на стороне клиента, либо через API сервера , вы можете отправлять сообщения в тему. Если вы впервые создаете запросы на отправку для FCM, см. руководство по вашей серверной среде и FCM , где содержится важная справочная информация и информация по настройке.
В логике отправки на серверной части укажите желаемое имя темы, как показано ниже:
Node.js
// The topic name can be optionally prefixed with "/topics/".
const topic = 'highScores';
const message = {
data: {
score: '850',
time: '2:45'
},
topic: topic
};
// Send a message to devices subscribed to the provided topic.
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
Джава
// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";
// See documentation on defining a message payload.
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setTopic(topic)
.build();
// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Питон
# The topic name can be optionally prefixed with "/topics/".
topic = 'highScores'
# See documentation on defining a message payload.
message = messaging.Message(
data={
'score': '850',
'time': '2:45',
},
topic=topic,
)
# Send a message to the devices subscribed to the provided topic.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
Идти
// The topic name can be optionally prefixed with "/topics/".
topic := "highScores"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Topic: topic,
}
// Send a message to the devices subscribed to the provided topic.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
С#
// The topic name can be optionally prefixed with "/topics/".
var topic = "highScores";
// See documentation on defining a message payload.
var message = new Message()
{
Data = new Dictionary<string, string>()
{
{ "score", "850" },
{ "time", "2:45" },
},
Topic = topic,
};
// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
ОТДЫХ
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"topic" : "foo-bar",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message"
}
}
}
URL-команда:
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message": {
"topic" : "foo-bar",
"notification": {
"body": "This is a Firebase Cloud Messaging Topic Message!",
"title": "FCM Message"
}
}
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Чтобы отправить сообщение в комбинацию тем, укажите условие , которое представляет собой логическое выражение, задающее целевые темы. Например, следующее условие будет отправлять сообщения на устройства, которые подписаны на TopicA
и TopicB
или TopicC
:
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"
FCM сначала оценивает любые условия в круглых скобках, а затем вычисляет выражение слева направо. В приведенном выше выражении пользователь, подписанный на какую-либо отдельную тему, не получает сообщение. Точно так же пользователь, не подписанный на TopicA
, не получит сообщение. Эти комбинации действительно получают его:
-
TopicA
иTopicB
-
TopicA
иTopicC
В условное выражение можно включить до пяти тем.
Для отправки в состояние:
Node.js
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
const condition = '\'stock-GOOG\' in topics || \'industry-tech\' in topics';
// See documentation on defining a message payload.
const message = {
notification: {
title: '$FooCorp up 1.43% on the day',
body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
},
condition: condition
};
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
Джава
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
String condition = "'stock-GOOG' in topics || 'industry-tech' in topics";
// See documentation on defining a message payload.
Message message = Message.builder()
.setNotification(Notification.builder()
.setTitle("$GOOG up 1.43% on the day")
.setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
.build())
.setCondition(condition)
.build();
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Питон
# Define a condition which will send to devices which are subscribed
# to either the Google stock or the tech industry topics.
condition = "'stock-GOOG' in topics || 'industry-tech' in topics"
# See documentation on defining a message payload.
message = messaging.Message(
notification=messaging.Notification(
title='$GOOG up 1.43% on the day',
body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
),
condition=condition,
)
# Send a message to devices subscribed to the combination of topics
# specified by the provided condition.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
Идти
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
condition := "'stock-GOOG' in topics || 'industry-tech' in topics"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Condition: condition,
}
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
С#
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";
// See documentation on defining a message payload.
var message = new Message()
{
Notification = new Notification()
{
Title = "$GOOG up 1.43% on the day",
Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
},
Condition = condition,
};
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
ОТДЫХ
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
"message":{
"condition": "'dogs' in topics || 'cats' in topics",
"notification" : {
"body" : "This is a Firebase Cloud Messaging Topic Message!",
"title" : "FCM Message",
}
}
}
URL-команда:
curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"notification": {
"title": "FCM Message",
"body": "This is a Firebase Cloud Messaging Topic Message!",
},
"condition": "'dogs' in topics || 'cats' in topics"
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1
Следующие шаги
- Вы можете использовать свой сервер для подписки экземпляров клиентских приложений на темы и выполнения других задач управления. См. раздел Управление подписками на темы на сервере .
- Узнайте больше о другом способе отправки на несколько устройств — Обмен сообщениями группы устройств.