Utilizzando FCM AndroidConfigV2, puoi inviare messaggi basati sugli intent ai dispositivi Android con una consegna tempestiva delle notifiche e un'API semplificata.
Questa guida spiega come eseguire la migrazione delle richieste di invio del backend da AndroidConfig
a AndroidConfigV2 e come aggiornare i client delle app per Android
dalla gestione precedente di onMessageReceived ai nuovi callback client v2
onNotificationReceived e onBackgroundSyncReceived.
Novità di AndroidConfigV2
L'API FCM AndroidConfigV2 semplifica l'esperienza degli sviluppatori introducendo due tipi di messaggi:
RemoteNotification: consigliato per tutti i messaggi FCM che mostrano una notifica urgente e sensibile al fattore tempo visibile all'utente. Questi messaggi bypassano qualsiasi misura di risparmio della batteria e vengono recapitati senza ritardi. Sul dispositivo, l'SDK FCM e Google Play Services si occupano della pubblicazione della notifica nelNotificationManagerdi Android.BackgroundSync: messaggi di dati non urgenti destinati alla sincronizzazione in background e agli aggiornamenti dello stato dell'app. La consegna può essere raggruppata o ritardata per ottimizzare la durata della batteria.
| Funzionalità | Legacy (AndroidConfig v1) |
Nuovo (AndroidConfigV2) |
|---|---|---|
| Campo di configurazione | message.android |
message.android_v2 |
| Definizione della priorità | priority: "high" o priority: "normal" esplicito |
Implicito dal tipo di unione (remote_notification per gli avvisi urgenti rispetto a background_sync per la sincronizzazione non urgente) |
| Pubblicazione di notifiche | L'app chiama manualmente NotificationManager.notify() |
L'SDK FCM e GMS Core pubblicano direttamente o utilizzando NotificationResponse |
| Callback client | • onMessageReceived(RemoteMessage)• onDeletedMessages() |
• onNotificationReceived(RemoteMessage)• onBackgroundSyncReceived(RemoteMessage)• onDeletedMessages() |
| Comprimibilità | Variabile; è richiesta un'impostazione esplicita | Entrambi i tipi di messaggi possono essere comprimibili o non comprimibili (non comprimibili per impostazione predefinita) |
Autorizza le richieste di invio di AndroidConfigV2
Puoi continuare a utilizzare i token di accesso OAuth 2.0 derivati dal tuo service account Firebase utilizzando le Credenziali predefinite dell'applicazione Google o l'SDK Admin e inviare richieste POST all'endpoint HTTP v1 messages:send.
Se non utilizzi il service account Firebase, assicurati di assegnare il tuo account dedicato al ruolo Firebase Cloud Messaging API Admin (roles/firebase.messagingAdmin)
e richiedi l'ambito OAuth 2.0 https://www.googleapis.com/auth/firebase.messaging
quando generi i token di accesso:
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
Aggiorna le richieste di invio del server (REST)
Per inviare una richiesta AndroidConfigV2 utilizzando l'API REST, sostituisci l'oggetto android nel corpo della richiesta con android_v2. All'interno di android_v2, specifica i parametri comuni (come ttl, collapse_key, data e restricted_package_name) e fornisci uno dei seguenti campi di unione: remote_notification o background_sync.
Invia un messaggio RemoteNotification
Per inviare una notifica urgente rivolta agli utenti, includi l'oggetto remote_notification e il relativo payload notification consigliato. Per impostazione predefinita, mutable_content
è impostato su false. GMS Core esegue immediatamente il rendering e pubblica la notifica nella barra delle applicazioni senza eseguire il codice dell'app in background.
Esempio JSON di richiesta HTTP completa (notifica con rendering automatico)
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
}
}
}
}
}
Invia una RemoteNotification con contenuti modificabili
Se la tua applicazione deve modificare la notifica sul dispositivo prima che venga visualizzata, imposta mutable_content: true all'interno di remote_notification. In questo modo, GMS Core viene associato alla tua applicazione client e richiama onNotificationReceived(). Questo è utile quando vuoi decriptare un payload con crittografia end-to-end, allegare avatar utente o localizzare stringhe.
Assicurati di includere un oggetto notification all'interno di remote_notification anche quando mutable_content è true. GMS Core utilizza questo oggetto notification come notifica di riserva se il callback del client scade o supera i limiti di soppressione.
Se stai eseguendo la migrazione dai messaggi di dati v1 legacy e vuoi che FCM invii il payload alle installazioni client v1 precedenti come messaggio di dati puro, imposta use_as_v1_data_message: true all'interno di remote_notification.
Esempio JSON di richiesta 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
}
}
}
}
}
Invia un messaggio BackgroundSync
Per inviare un messaggio non urgente per la sincronizzazione dei dati in background, gli aggiornamenti dello stato silenzioso o l'aggiornamento di un badge o di un widget dell'app, utilizza l'oggetto background_sync.
Non utilizzare questi messaggi per pubblicare notifiche visibili agli utenti, in quanto possono essere raggruppati o ritardati per ottimizzare la durata della batteria del dispositivo.
Esempio JSON di richiesta 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": {}
}
}
}
Aggiorna i callback del client Android
Per ricevere messaggi AndroidConfigV2 su Android, esegui l'upgrade della tua app in modo che utilizzi l'SDK firebase-messaging più recente. Aggiorna il servizio estendendo FirebaseMessagingService implementando onNotificationReceived() e onBackgroundSyncReceived().
Installa l'SDK EAP
Durante l'EAP, l'SDK firebase-messaging v2 viene distribuito come archivio del repository Maven locale anziché tramite il repository Maven pubblico di Google.
Aggiungi la directory
m2repositorycontenentefirebase-messaging:26.1.0-eap01alla directory root del tuo progetto Android (<project-root>/m2repository) utilizzando una delle seguenti opzioni:- Opzione A: scarica l'archivio predefinito: scarica
FirebaseMessaging_26.1.0-eap01.zip
ed estrai la directory
m2repositorynella directory root del tuo progetto Android (<project-root>/m2repository). Opzione B: crea da GitHub con Gradle: clona il branch
feature/fcm-android-config-v2-eapdifirebase/firebase-android-sdk, crea il repository Maven locale e copia la directorybuild/m2repositorygenerata nella directory principale del progetto 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
- Opzione A: scarica l'archivio predefinito: scarica
FirebaseMessaging_26.1.0-eap01.zip
ed estrai la directory
Nel file
settings.gradle.kts(osettings.gradle) a livello di progetto, aggiungi la directorym2repositorylocale all'inizio del bloccorepositories, sopragoogle():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() } }Nel file
app/build.gradle.kts(oapp/build.gradle) a livello di modulo, aggiorna la dipendenzafirebase-messagingin26.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' }Sincronizza il progetto con i file Gradle.
Gestisci le notifiche remote con onNotificationReceived
Con AndroidConfigV2, i messaggi RemoteNotification vengono visualizzati, a meno che mutable_content non sia impostato su true o non siano esplicitamente disattivati in onNotificationReceived().
Quando arriva un RemoteNotification con mutable_content: true, GMS Core si associa
alla tua applicazione e chiama onNotificationReceived(). Il metodo deve restituire un NotificationResponse entro 20 secondi.
Restituisci una notifica modificata
L'oggetto Notification che passi a NotificationResponse.create sostituisce le proprietà del payload di riserva remote_notification.notification del server definite nella richiesta di invio. Per conservare i valori della richiesta di invio, leggili da message.notification (message.getNotification() in Java) mentre applichi le modifiche on-device:
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());
}
}
Elimina una notifica
Se l'utente ha la schermata o la chat pertinente attiva in questo momento, puoi sopprimere la notifica restituendo 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());
}
Notifiche in streaming o annullamento degli avvisi meno recenti (FcmNotificationManager)
Se devi pubblicare più notifiche per una singola notifica push in arrivo o annullare una notifica obsoleta prima di visualizzarne una nuova, utilizza 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();
}
Gestisci i messaggi BackgroundSync utilizzando onBackgroundSyncReceived
Per elaborare i messaggi BackgroundSync su Android, utilizza
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.
}
Gestisci le eliminazioni dei messaggi in attesa utilizzando onDeletedMessages
In alcune situazioni, ad esempio quando un dispositivo non si connette a FCM per un periodo di tempo prolungato o quando la coda del server è piena, FCM potrebbe eliminare i messaggi in attesa prima della consegna. In questi casi, esegui l'override di 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();
}
Esegui la migrazione di app specifiche
Inviare notifiche con crittografia end-to-end (E2EE)
Quando invii una notifica con crittografia end-to-end utilizzando un
RemoteNotification, i contenuti della notifica decriptati
rimangono all'interno della tua app e della piattaforma Android:
- Invia una notifica modificabile:
il tuo server invia un
RemoteNotificationconmutable_content: true, il payload criptato indatae un backup generico non criptatonotification. GMS Core invia il messaggio criptato all'SDK FCM open source all'interno della tua app. - Decripta e restituisci la notifica: l'SDK FCM richiama
onNotificationReceived(). La tua app decripta il payload localmente, crea l'AndroidNotificationdecriptato finale e lo restituisce all'SDK FCM open source utilizzandoNotificationResponseoFcmNotificationManager. - Pubblicazione sulla piattaforma e segnalazione dei metadati: l'SDK FCM open source pubblica la notifica decriptata direttamente nell'API
NotificationManagerdella piattaforma Android e invia solo i metadati della notifica, come gli ID e i timestamp delle notifiche, a GMS Core per l'osservabilità della distribuzione. I contenuti decriptati non vengono mai inviati a GMS Core. - Pubblica una notifica di backup, se necessario: solo se l'app non risponde entro il timeout di 20 secondi o supera i limiti di soppressione in background, GMS Core pubblica il backup generico
notificationdirettamente sulla piattaforma Android.

Informazioni sulla soppressione e sui timeout delle notifiche
Per mantenere una distribuzione affidabile nell'ecosistema Android, GMS Core applica timeout di elaborazione e limiti di soppressione delle notifiche durante la gestione dei messaggi RemoteNotification:
Timeout di elaborazione
Quando mutable_content è impostato su true, il metodo onNotificationReceived() deve restituire un NotificationResponse entro 20 secondi. Se l'esecuzione supera questa soglia, il callback viene annullato e GMS Core pubblica automaticamente una notifica di riserva visualizzata dal payload remote_notification.notification.
Tasso di soppressione delle notifiche
Poiché i messaggi RemoteNotification bypassano le limitazioni di Doze per avvisare immediatamente gli utenti e vengono recapitati senza ritardi, le applicazioni devono mostrare le notifiche per i messaggi RemoteNotification ricevuti.
Ogni applicazione può sopprimere fino al 25% del traffico RemoteNotification durante l'esecuzione in background. Se il tasso di soppressione di un'applicazione supera il 25%, GMS Core esegue automaticamente il rendering e pubblica una notifica di riserva dal payload remote_notification.notification.
Le soppressioni eseguite quando l'applicazione è attiva in primo piano non vengono conteggiate ai fini di questa soglia. Anche le applicazioni a cui sono state concesse autorizzazioni di utilizzo in background senza limitazioni sono esenti dai limiti di soppressione in background.