Уведомления Firebase ведут себя по-разному в зависимости от того, находится ли приложение в активном или фоновом режиме. Если вы хотите, чтобы активные приложения получали уведомления или сообщения с данными, вам потребуется написать код для обработки обратного вызова onMessageReceived
. Разницу между уведомлениями и сообщениями с данными см. в разделе Типы сообщений .
Обработка сообщений
Для получения сообщений используйте службу, расширяющую FirebaseMessagingService
. Ваша служба должна переопределить обратные вызовы onMessageReceived
и onDeletedMessages
.
onMessageReceived
предоставляется для большинства типов сообщений, за следующими исключениями:
Уведомления, отправляемые, когда приложение работает в фоновом режиме . В этом случае уведомление отображается в области уведомлений устройства. При нажатии на уведомление по умолчанию открывается панель запуска приложений.
Сообщения, содержащие как уведомления, так и данные, при получении в фоновом режиме . В этом случае уведомление доставляется в системный трей устройства, а данные — в дополнительные элементы, соответствующие цели вашего приложения-запуска.
В итоге:
Состояние приложения | Уведомление | Данные | Оба |
---|---|---|---|
Передний план | onMessageReceived | onMessageReceived | onMessageReceived |
Фон | Системный лоток | onMessageReceived | Уведомление: системный трей Данные: в дополнениях к намерению. |
Обратному вызову onMessageReceived
задаются тайм-ауты, позволяющие просто опубликовать уведомление, но таймеры не предназначены для предоставления приложению доступа к сети или выполнения дополнительных задач. Таким образом, если ваше приложение выполняет что-то более сложное, вам необходимо выполнить дополнительные действия, чтобы гарантировать, что приложение сможет завершить свою работу.
Если вы ожидаете, что вашему приложению потребуется около 10 секунд для обработки сообщения, вам следует запланировать задание WorkManager или следовать приведенным ниже рекомендациям по WakeLock . В некоторых случаях временное окно для обработки сообщения может быть короче 10 секунд в зависимости от задержек, возникших до вызова 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 отображает пользовательский значок по умолчанию для
- Все уведомительные сообщения, отправленные из редактора уведомлений .
- Любое уведомительное сообщение, которое явно не устанавливает значок в полезной нагрузке уведомления.
Android использует пользовательский цвет по умолчанию для
- Все уведомительные сообщения, отправленные из редактора уведомлений .
- Любое уведомительное сообщение, в котором явно не указан цвет в полезной нагрузке уведомления.
Если не установлен пользовательский значок по умолчанию и в полезной нагрузке уведомления не установлен значок, Android отображает значок приложения белым цветом.
Переопределение onMessageReceived
Переопределив метод FirebaseMessagingService.onMessageReceived
, вы можете выполнять действия на основе полученного объекта RemoteMessage и получать данные сообщения:
Kotlin
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. }
Поддерживайте устройство в активном состоянии при обработке сообщений FCM
Если вашему приложению необходимо поддерживать устройство в спящем режиме во время обработки сообщения FCM, ему потребуется удерживать WakeLock в течение этого времени или создать задание WorkManager. WakeLock хорошо подходят для коротких обрабатываемых действий, которые могут превышать тайм-ауты onMessageReceived
по умолчанию. Для продолжительных рабочих процессов, таких как отправка нескольких последовательных RPC-запросов на серверы, использование задания WorkManager предпочтительнее, чем WakeLock. В этом разделе мы рассмотрим использование WakeLock. WakeLock предотвращает переход устройства в спящий режим во время работы приложения, что может привести к повышенному расходу заряда батареи, поэтому использование WakeLock следует зарезервировать для случаев, когда приложение не должно быть приостановлено во время обработки сообщения, например:
- Уведомления пользователю, срочные.
- Взаимодействие с чем-либо вне устройства, которое не должно прерываться (например, сетевые передачи данных или связь с другим устройством, например, сопряженными часами).
Сначала вам нужно убедиться, что ваше приложение запрашивает разрешение WakeLock (FCM SDK включает его по умолчанию, поэтому обычно ничего добавлять не нужно).
<uses-permission android:name="android.permission.WAKE_LOCK" />
Затем вашему приложению потребуется получить WakeLock в начале обратного вызова FirebaseMessagingService.onMessageReceived()
и снять его в конце обратного вызова.
Пользовательский FirebaseMessagingService
приложения:
@Override public void onMessageReceived(final RemoteMessage message) { // If this is a message that is time sensitive or shouldn't be interrupted WakeLock wakeLock = getSystemService(PowerManager.class).newWakeLock(PARTIAL_WAKE_LOCK, "myApp:messageReceived"); try { wakeLock.acquire(TIMEOUT_MS); // handle message ... finally { wakeLock.release(); } }
Переопределение onDeletedMessages
В некоторых ситуациях FCM может не доставить сообщение. Это происходит, когда на момент подключения к устройству на вашем устройстве слишком много сообщений (>100), ожидающих отправки, или если устройство не подключалось к FCM более месяца. В таких случаях может быть получен обратный вызов FirebaseMessagingService.onDeletedMessages()
. При получении этого обратного вызова экземпляр приложения должен выполнить полную синхронизацию с вашим сервером приложений. Если вы не отправляли сообщение приложению на этом устройстве в течение последних 4 недель, FCM не вызовет onDeletedMessages()
.Обработка уведомлений в фоновом режиме приложения
Когда приложение работает в фоновом режиме, Android направляет уведомления в системный трей. При нажатии на уведомление по умолчанию открывается панель запуска приложений.
Это включает сообщения, содержащие как уведомления, так и данные (а также все сообщения, отправленные из консоли уведомлений). В этих случаях уведомление доставляется в системный трей устройства, а данные — в дополнительные элементы, соответствующие цели вашего приложения-запуска.
Для получения более подробной информации о доставке сообщений в ваше приложение см. панель отчетности FCM , на которой регистрируется количество отправленных и открытых сообщений на устройствах Apple и Android, а также данные о «показах» (уведомлениях, увиденных пользователями) для приложений Android.
Получать сообщения FCM в режиме прямой загрузки
Разработчики, желающие отправлять сообщения FCM приложениям ещё до разблокировки устройства, могут включить получение сообщений в приложении Android, когда устройство находится в режиме прямой загрузки. Например, вы можете захотеть, чтобы пользователи вашего приложения получали уведомления о тревоге даже на заблокированном устройстве.
При реализации этого варианта использования соблюдайте общие рекомендации и ограничения для режима прямой загрузки . Особенно важно учитывать видимость сообщений, связанных с прямой загрузкой; любой пользователь, имеющий доступ к устройству, может просматривать эти сообщения без ввода учётных данных.
Предпосылки
- Устройство должно быть настроено для режима прямой загрузки.
- На устройстве должна быть установлена последняя версия сервисов Google Play (19.0.54 или более поздняя).
- Для получения сообщений FCM приложение должно использовать FCM SDK (
com.google.firebase:firebase-messaging
).
Включите обработку сообщений режима прямой загрузки в вашем приложении
В файле Gradle уровня приложения добавьте зависимость от библиотеки поддержки прямой загрузки FCM:
implementation 'com.google.firebase:firebase-messaging-directboot:20.2.0'
Включите прямую загрузку
FirebaseMessagingService
в приложении, добавив атрибутandroid:directBootAware="true"
в манифест приложения:<service android:name=".java.MyFirebaseMessagingService" android:exported="false" android:directBootAware="true"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
Важно убедиться, что FirebaseMessagingService
может работать в режиме прямой загрузки. Проверьте следующие требования:
- Служба не должна получать доступ к защищенному хранилищу учетных данных при работе в режиме прямой загрузки.
- Служба не должна пытаться использовать компоненты, такие как
Activities
,BroadcastReceivers
или другиеServices
, которые не помечены как поддерживающие прямую загрузку, при работе в режиме прямой загрузки. - Любые библиотеки, используемые службой, также не должны обращаться к хранилищу, защищённому учётными данными, и вызывать компоненты, не поддерживающие DirectBootAware, при работе в режиме прямой загрузки. Это означает, что любые библиотеки, используемые приложением и вызываемые из службы, либо должны поддерживать прямую загрузку, либо приложение должно проверять, запущено ли оно в режиме прямой загрузки, и не вызывать их в этом режиме. Например, Firebase SDK работают с прямой загрузкой (их можно включить в приложение, не вызывая сбоя в режиме прямой загрузки), но многие Firebase API не поддерживают вызов в режиме прямой загрузки.
- Если приложение использует пользовательское
Application
, тоApplication
также должно поддерживать прямую загрузку (без доступа к защищенному хранилищу учетных данных в режиме прямой загрузки).
Инструкции по отправке сообщений на устройства в режиме прямой загрузки см. в разделе Отправка сообщений с включенной прямой загрузкой .