Com o FCM AndroidConfigV2, é possível enviar mensagens
orientadas por intent para dispositivos Android com entrega de notificações em tempo hábil e uma
API simplificada.
Este guia aborda como migrar suas solicitações de envio de back-end do AndroidConfig
para o AndroidConfigV2 e como atualizar os clientes do app Android
do processamento legado do onMessageReceived para os novos callbacks de cliente v2
onNotificationReceived e onBackgroundSyncReceived.
Novidades no AndroidConfigV2
A API FCM AndroidConfigV2 simplifica a experiência do desenvolvedor ao introduzir dois tipos de mensagem:
RemoteNotification: recomendado para todas as mensagens do FCM que mostram uma notificação urgente e com prazo de validade visível para o usuário. Essas mensagens ignoram as medidas de economia de bateria e são entregues sem atraso. No dispositivo, o SDK do FCM e o Google Play Services assumem a responsabilidade de postar a notificação noNotificationManagerdo Android.BackgroundSync: mensagens de dados não urgentes destinadas à sincronização em segundo plano e atualizações de estado do app. A entrega pode ser feita em lote ou atrasada para otimizar a duração da bateria.
| Recurso | Legado (AndroidConfig v1) |
Novo (AndroidConfigV2) |
|---|---|---|
| Campo de configuração | message.android |
message.android_v2 |
| Definição de prioridade | priority: "high" ou priority: "normal" explícito |
Implícito pelo tipo de união (remote_notification para alertas urgentes versus background_sync para sincronização não urgente) |
| Postagem de notificações | O app chama NotificationManager.notify() manualmente |
O SDK do FCM e o GMS Core postam diretamente ou usando o NotificationResponse. |
| Callbacks do cliente | • onMessageReceived(RemoteMessage)• onDeletedMessages() |
• onNotificationReceived(RemoteMessage)• onBackgroundSyncReceived(RemoteMessage)• onDeletedMessages() |
| Recolhimento | Variado; configuração explícita obrigatória | Os dois tipos de mensagem podem ser recolhíveis ou não recolhíveis (não recolhíveis por padrão). |
Autorizar solicitações de envio do AndroidConfigV2
Você pode continuar usando tokens de acesso do OAuth 2.0 derivados da sua conta de serviço do Firebase com o Application Default Credentials do Google ou o SDK Admin e enviar solicitações POST para o endpoint messages:send do HTTP v1.
Se você não estiver usando sua conta de serviço do Firebase, atribua sua conta dedicada ao papel de administrador da API Firebase Cloud Messaging (roles/firebase.messagingAdmin)
e solicite o escopo do OAuth 2.0 https://www.googleapis.com/auth/firebase.messaging
ao gerar tokens de acesso:
POST https://fcm.googleapis.com/v1/projects/YOUR_PROJECT_ID/messages:send HTTP/1.1
Authorization: Bearer YOUR_OAUTH_ACCESS_TOKEN
Content-Type: application/json
Atualizar solicitações de envio do servidor (REST)
Para enviar uma solicitação AndroidConfigV2 usando a API REST, substitua o objeto android no corpo da solicitação por android_v2. Em android_v2, especifique
parâmetros comuns (como ttl, collapse_key, data e
restricted_package_name) e forneça um dos seguintes campos de união:
remote_notification ou background_sync.
Enviar uma mensagem RemoteNotification
Para enviar uma notificação urgente voltada ao usuário, inclua o objeto remote_notification
e o payload notification recomendado. Por padrão, mutable_content
é definido como falso. O GMS Core renderiza e publica imediatamente a notificação na
bandeja do sistema sem executar o código do app em segundo plano.
Exemplo de JSON de solicitação HTTP completa (notificação renderizada automaticamente)
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": {
"token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification": {
"title": "FCM Message",
"body": "This is an FCM notification message!"
},
"android_v2": {
"ttl": "3600s",
"remote_notification": {
"mutable_content": false,
"notification": {
"title": "Order update",
"body": "Your order has been shipped!",
"icon": "ic_notification_custom",
"sound": "default",
"tag": "alert_tag_1",
"id": 100
}
}
}
}
}
Enviar uma RemoteNotification com conteúdo mutável
Se o aplicativo precisar modificar a notificação no dispositivo antes de ser
exibida, defina mutable_content: true dentro de remote_notification. Isso
instrui o GMS Core a se vincular ao aplicativo cliente e invocar
onNotificationReceived(). Isso é útil quando você quer descriptografar um
payload criptografado de ponta a ponta, anexar avatares de usuário ou
localizar strings.
Inclua um objeto notification dentro de remote_notification mesmo
quando mutable_content for true. O GMS Core usa esse objeto notification como
a notificação substituta se o callback do cliente expirar ou exceder
os limites de supressão.
Se você estiver migrando de mensagens de dados legadas da v1 e quiser que o FCM
entregue o payload para instalações de cliente mais antigas da v1 como uma mensagem de dados pura, defina
use_as_v1_data_message: true dentro de remote_notification.
Exemplo de JSON de solicitação HTTP completa
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": {
"token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data": {
"encrypted_content": "U2FsdGVkX19vN2m+",
"sender_id": "user_98124"
},
"android_v2": {
"ttl": "3600s",
"remote_notification": {
"mutable_content": true,
"use_as_v1_data_message": true,
"notification": {
"title": "New message",
"body": "You have a new message",
"tag": "chat_alert",
"id": 1001
}
}
}
}
}
Enviar uma mensagem de BackgroundSync
Para enviar uma mensagem não urgente para sincronização de dados em segundo plano, atualizações de estado silenciosas ou atualização de um selo ou widget de app, use o objeto background_sync.
Não use essas mensagens para postar
notificações visíveis ao usuário, porque elas podem ser agrupadas ou atrasadas para otimizar
a duração da bateria do dispositivo.
Exemplo de JSON de solicitação HTTP completa
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": {
"token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data": {
"score": "FETCH_UPDATES",
"sync_action": "FETCH_UPDATES"
},
"android_v2": {
"ttl": "86400s",
"collapse_key": "app_state_sync",
"background_sync": {}
}
}
}
Atualizar callbacks do cliente Android
Para receber mensagens do AndroidConfigV2 no Android, atualize seu app para usar a
versão mais recente do SDK do firebase-messaging. Atualize o serviço que estende
FirebaseMessagingService implementando onNotificationReceived() e
onBackgroundSyncReceived().
Instalar o SDK do EAP
Durante o EAP, o SDK do firebase-messaging v2 é distribuído como um arquivo de repositório Maven local, em vez de ser disponibilizado pelo repositório Maven público do Google.
Adicione o diretório
m2repositoryque contémfirebase-messaging:26.1.0-eap01ao diretório raiz do seu projeto do Android (<project-root>/m2repository) usando uma das seguintes opções:- Opção A: fazer o download do arquivo pré-criado: faça o download de
FirebaseMessaging_26.1.0-eap01.zip
e extraia o diretório
m2repositoryno diretório raiz do seu projeto do Android (<project-root>/m2repository). Opção B: criar no GitHub com o Gradle: clone a ramificação
feature/fcm-android-config-v2-eapdefirebase/firebase-android-sdk, crie o repositório Maven local e copie o diretóriobuild/m2repositorygerado para a raiz do projeto do Android:git clone --branch feature/fcm-android-config-v2-eap --single-branch \ https://github.com/firebase/firebase-android-sdk.git cd firebase-android-sdk ./gradlew -PprojectsToPublish="firebase-messaging" firebasePublish cp -R build/m2repository /path/to/your/android-project/m2repository
- Opção A: fazer o download do arquivo pré-criado: faça o download de
FirebaseMessaging_26.1.0-eap01.zip
e extraia o diretório
No
settings.gradle.kts(ousettings.gradle) para envolvidos no projeto, adicione o diretóriom2repositorylocal à parte de cima do blocorepositories, acima degoogle():Kotlin
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url = uri("${rootDir}/m2repository") } google() mavenCentral() } }Groovy
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url "${rootDir}/m2repository" } google() mavenCentral() } }No
app/build.gradle.kts(ouapp/build.gradle) do módulo, atualize a dependênciafirebase-messagingpara26.1.0-eap01:Kotlin
dependencies { implementation("com.google.firebase:firebase-messaging:26.1.0-eap01") }Groovy
dependencies { implementation 'com.google.firebase:firebase-messaging:26.1.0-eap01' }Sincronize o projeto com arquivos do Gradle.
Processar RemoteNotifications com onNotificationReceived
Com AndroidConfigV2, as mensagens RemoteNotification são exibidas,
a menos que mutable_content esteja definido como verdadeiro ou que sejam explicitamente silenciadas em
onNotificationReceived().
Quando um RemoteNotification chega com mutable_content: true, o GMS Core se vincula
ao aplicativo e chama onNotificationReceived(). O método precisa retornar um NotificationResponse em até 20 segundos.
Retornar uma notificação modificada
O objeto Notification transmitido para NotificationResponse.create substitui as
propriedades de payload de substituição remote_notification.notification do servidor definidas
na solicitação de envio. Para manter os valores da solicitação de envio, leia-os em
message.notification (message.getNotification() em Java) ao aplicar
modificações no dispositivo:
Kotlin
import androidx.core.app.NotificationCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.NotificationResponse
import com.google.firebase.messaging.RemoteMessage
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onNotificationReceived(message: RemoteMessage): NotificationResponse {
val serverNotif = message.notification
val channelId = serverNotif?.channelId ?: "default_channel"
// Keep the server-defined title unchanged, or fall back to default
val title = serverNotif?.title ?: "New message"
// Modify the notification body on-device (for example, decrypting data)
val decryptedBody = decryptPayload(message.data["encrypted_content"])
val builder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(title)
.setContentText(decryptedBody)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true)
// Return the response for the open-source FCM SDK to post to the Android platform
return NotificationResponse.create("optional_tag", 100, builder.build())
}
}
Java
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import com.google.firebase.messaging.NotificationResponse;
import androidx.core.app.NotificationCompat;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public NotificationResponse onNotificationReceived(RemoteMessage message) {
RemoteMessage.Notification serverNotif = message.getNotification();
String channelId = (serverNotif != null && serverNotif.getChannelId() != null)
? serverNotif.getChannelId()
: "default_channel";
// Keep the server-defined title unchanged, or fall back to default
String title = (serverNotif != null && serverNotif.getTitle() != null)
? serverNotif.getTitle()
: "New message";
// Modify the notification body on-device (for example, decrypting data)
String decryptedBody = decryptPayload(message.getData().get("encrypted_content"));
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(title)
.setContentText(decryptedBody)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true);
// Return the response for the open-source FCM SDK to post to the Android platform
return NotificationResponse.create("optional_tag", 100, builder.build());
}
}
Suprimir uma notificação
Se o usuário estiver com a tela ou o chat relevante ativo no momento, você poderá suprimir
a notificação retornando NotificationResponse.suppress():
Kotlin
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner
override fun onNotificationReceived(message: RemoteMessage): NotificationResponse {
val chatId = message.data["chat_id"]
val isAppForeground = ProcessLifecycleOwner.get()
.lifecycle
.currentState
.isAtLeast(Lifecycle.State.STARTED)
if (isAppForeground && chatRepository.isConversationActive(chatId)) {
// Suppress notification display because the user is actively viewing this chat
return NotificationResponse.suppress()
}
val builder = buildNotificationForChat(message)
return NotificationResponse.create("chat_tag", 101, builder.build())
}
Java
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.ProcessLifecycleOwner;
@Override
public NotificationResponse onNotificationReceived(RemoteMessage message) {
String chatId = message.getData().get("chat_id");
boolean isAppForeground = ProcessLifecycleOwner.get()
.getLifecycle()
.getCurrentState()
.isAtLeast(Lifecycle.State.STARTED);
if (isAppForeground && chatRepository.isConversationActive(chatId)) {
// Suppress notification display because the user is actively viewing this chat
return NotificationResponse.suppress();
}
NotificationCompat.Builder builder = buildNotificationForChat(message);
return NotificationResponse.create("chat_tag", 101, builder.build());
}
Notificações de transmissão ou cancelamento de alertas mais antigos (FcmNotificationManager)
Se você precisar postar várias notificações para um único push recebido ou cancelar
uma notificação desatualizada antes de mostrar uma nova, use FcmNotificationManager:
Kotlin
override fun onNotificationReceived(message: RemoteMessage): NotificationResponse {
// Retrieve the scoped manager for this message execution
val manager = getFcmNotificationManager(message)
// 1. Cancel an outdated notification right away
manager.cancelNow("message_tag", 50)
// 2. Post the item notification immediately
val itemNotif = NotificationCompat.Builder(this, "chat_channel")
.setSmallIcon(R.drawable.ic_message)
.setContentTitle("Alex")
.setContentText(message.data["text"])
manager.postNow("item_tag", 51, itemNotif.build())
// 3. Post a group summary notification
val summaryNotif = NotificationCompat.Builder(this, "chat_channel")
.setSmallIcon(R.drawable.ic_message)
.setContentTitle("New Conversations")
.setGroupSummary(true)
manager.postNow("summary_tag", 52, summaryNotif.build())
// 4. Return finished() to complete the streaming workflow
return manager.finished()
}
Java
@Override
public NotificationResponse onNotificationReceived(RemoteMessage message) {
// Retrieve the scoped manager for this message execution
FcmNotificationManager manager = getFcmNotificationManager(message);
// 1. Cancel an outdated notification right away
manager.cancelNow("message_tag", 50);
// 2. Post the item notification immediately
NotificationCompat.Builder itemNotif = new NotificationCompat.Builder(this, "chat_channel")
.setSmallIcon(R.drawable.ic_message)
.setContentTitle("Alex")
.setContentText(message.getData().get("text"));
manager.postNow("item_tag", 51, itemNotif.build());
// 3. Post a group summary notification
NotificationCompat.Builder summaryNotif = new NotificationCompat.Builder(this, "chat_channel")
.setSmallIcon(R.drawable.ic_message)
.setContentTitle("New Conversations")
.setGroupSummary(true);
manager.postNow("summary_tag", 52, summaryNotif.build());
// 4. Return finished() to complete the streaming workflow
return manager.finished();
}
Processar mensagens de BackgroundSync usando onBackgroundSyncReceived
Para processar mensagens BackgroundSync no Android, use
onBackgroundSyncReceived():
Kotlin
override fun onBackgroundSyncReceived(message: RemoteMessage) {
val syncCommand = message.data["sync_action"]
try {
// Perform local database synchronization or cache refresh
AppDataRepository.getInstance(applicationContext).syncWithServer(syncCommand)
} catch (e: Exception) {
Log.e("FCM", "Background sync operation failed", e)
}
// Execution completes -> GMS Core marks the message as handled and unbinds.
}
Java
@Override
public void onBackgroundSyncReceived(RemoteMessage message) {
String syncCommand = message.getData().get("sync_action");
try {
// Perform local database synchronization or cache refresh
AppDataRepository.getInstance(getApplicationContext()).syncWithServer(syncCommand);
} catch (Exception e) {
Log.e("FCM", "Background sync operation failed", e);
}
// Execution completes -> GMS Core marks the message as handled and unbinds.
}
Processar exclusões de mensagens pendentes usando onDeletedMessages
Em algumas situações, como quando um dispositivo não se conecta ao FCM por
um período prolongado ou quando a fila do servidor está cheia, o FCM pode excluir
mensagens pendentes antes da entrega. Nesses casos, substitua
onDeletedMessages():
Kotlin
override fun onDeletedMessages() {
// Perform a full state synchronization with your app server
AppDataRepository.getInstance(applicationContext).scheduleFullSync()
}
Java
@Override
public void onDeletedMessages() {
// Perform a full state synchronization with your app server
AppDataRepository.getInstance(getApplicationContext()).scheduleFullSync();
}
Migrar apps específicos
Enviar notificações criptografadas de ponta a ponta (E2EE)
Ao enviar uma notificação criptografada de ponta a ponta usando um
RemoteNotification, o conteúdo descriptografado
permanece no app e na plataforma Android:
- Enviar notificação mutável:
o servidor envia um
RemoteNotificationcommutable_content: true, o payload criptografado emdatae um backup genérico não criptografadonotification. O GMS Core envia a mensagem criptografada para o SDK de código aberto FCM no seu app. - Descriptografar e retornar a notificação: o
SDK do FCM invoca
onNotificationReceived(). O app descriptografa o payload localmente, cria oNotificationdo Android descriptografado final e o transmite de volta ao SDK de código aberto FCM usandoNotificationResponseouFcmNotificationManager. - Postar na plataforma e informar metadados: o SDK de código aberto do FCM
posta a notificação descriptografada diretamente na API
NotificationManagerda plataforma Android e envia apenas metadados de notificação, como IDs de notificação e carimbos de data/hora, de volta ao GMS Core para observabilidade de entrega. O conteúdo descriptografado nunca é enviado ao GMS Core. - Postar uma notificação de backup, se necessário: somente se o app não responder
dentro do tempo limite de 20 segundos ou exceder os limites de supressão
em segundo plano, o GMS Core vai postar o
notificationde backup genérico diretamente na plataforma Android.

Entender a supressão e os tempos limite de notificações
Para manter uma entrega confiável em todo o ecossistema Android, o GMS Core aplica
tempos limite de processamento e limites de supressão de notificações ao processar
mensagens RemoteNotification:
Tempo limite de processamento
Quando mutable_content é definido como true, o método onNotificationReceived()
precisa retornar um NotificationResponse em até 20 segundos. Se
a execução exceder esse limite, o callback será cancelado e o GMS Core
vai postar automaticamente uma notificação de fallback renderizada do
payload remote_notification.notification.
Taxa de supressão de notificações
Como as mensagens RemoteNotification ignoram as restrições do Doze para alertar os usuários
imediatamente e são entregues sem atraso, os aplicativos precisam
mostrar notificações para as mensagens RemoteNotification recebidas.
Cada aplicativo pode suprimir até
25% do tráfego de RemoteNotification enquanto é executado
em segundo plano. Se a taxa de supressão de um aplicativo exceder
25%, o GMS Core vai renderizar e postar automaticamente uma
notificação substituta renderizada do payload
remote_notification.notification.
As supressões realizadas quando o aplicativo está ativo em primeiro plano não são contabilizadas nesse limite. Os aplicativos que recebem permissões de uso em segundo plano irrestrito também estão isentos dos limites de supressão em segundo plano.