Za pomocą FCM AndroidConfigV2 możesz wysyłać wiadomości oparte na intencjach na urządzenia z Androidem, korzystając z uproszczonego interfejsu API i zapewniając terminowe dostarczanie powiadomień.
Z tego przewodnika dowiesz się, jak przenieść żądania wysyłania z backendu z AndroidConfig do AndroidConfigV2 oraz jak zaktualizować klientów aplikacji na Androida ze starszej obsługi onMessageReceived do nowych wywołań zwrotnych klienta w wersji 2 onNotificationReceived i onBackgroundSyncReceived.
Nowości w AndroidConfigV2
Interfejs FCM AndroidConfigV2 API upraszcza pracę deweloperów, wprowadzając 2 typy wiadomości:
RemoteNotification: zalecane w przypadku wszystkich wiadomości FCM, które wyświetlają pilne, ważne powiadomienie widoczne dla użytkownika. Te wiadomości omijają wszelkie środki oszczędzania baterii i są dostarczane bez opóźnień. Na urządzeniu pakiet SDK FCM i usługi Google Play przejmują kontrolę nad publikowaniem powiadomień wNotificationManagerAndroida.BackgroundSync: wiadomości z danymi, które nie są pilne, przeznaczone do synchronizacji w tle i aktualizacji stanu aplikacji. Dostarczanie może być grupowane lub opóźniane, aby zoptymalizować czas pracy na baterii.
| Funkcja | Starsza wersja (AndroidConfig v1) |
Nowe (AndroidConfigV2) |
|---|---|---|
| Pole konfiguracji | message.android |
message.android_v2 |
| Definicja priorytetu | Wyraźny priority: "high" lub priority: "normal" |
Wynika z typu unii (remote_notification w przypadku pilnych alertów i background_sync w przypadku synchronizacji, która nie jest pilna) |
| Publikowanie powiadomień | Aplikacja ręcznie wywołuje NotificationManager.notify() |
Pakiet SDK FCM i usługi GMS Core publikują dane bezpośrednio lub za pomocą NotificationResponse |
| Wywołania zwrotne klienta | • onMessageReceived(RemoteMessage)• onDeletedMessages() |
• onNotificationReceived(RemoteMessage)• onBackgroundSyncReceived(RemoteMessage)• onDeletedMessages() |
| Możliwość zwijania | Różne; wymagane jest jawne ustawienie | Oba typy wiadomości mogą być zwijane lub nie (domyślnie nie są zwijane). |
Autoryzowanie żądań wysyłania AndroidConfigV2
Możesz nadal używać tokenów dostępu OAuth 2.0 pochodzących z konta usługi Firebase za pomocą domyślnego uwierzytelniania aplikacji Google lub pakietu Admin SDK i wysyłać żądania POST do punktu końcowego HTTP v1 messages:send.
Jeśli nie używasz konta usługi Firebase, pamiętaj, aby przypisać swoje dedykowane konto do roli Administrator interfejsu Komunikacji w chmurze Firebase (FCM) API (roles/firebase.messagingAdmin) i poprosić o zakres protokołu OAuth 2.0 https://www.googleapis.com/auth/firebase.messaging podczas generowania tokenów dostępu:
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
Aktualizowanie żądań wysyłania serwera (REST)
Aby wysłać żądanie AndroidConfigV2 za pomocą interfejsu API REST, zastąp obiekt android w treści żądania obiektem android_v2. W obiekcie android_v2 określ parametry wspólne (takie jak ttl, collapse_key, data i restricted_package_name) oraz podaj jedno z tych pól unii: remote_notification lub background_sync.
Wysyłanie wiadomości RemoteNotification
Aby wysłać pilne powiadomienie dla użytkownika, dołącz obiekt remote_notification i zalecane dane notification. Domyślnie parametr mutable_content ma wartość „false”. GMS Core natychmiast renderuje i publikuje powiadomienie w obszarze powiadomień bez wykonywania kodu aplikacji działającej w tle.
Przykładowy kod JSON pełnego żądania HTTP (powiadomienie renderowane automatycznie)
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
}
}
}
}
}
Wysyłanie powiadomienia RemoteNotification z treścią, którą można modyfikować
Jeśli aplikacja musi zmodyfikować powiadomienie na urządzeniu, zanim zostanie ono wyświetlone, ustaw mutable_content: true wewnątrz remote_notification. Spowoduje to, że GMS Core połączy się z aplikacją kliencką i wywoła onNotificationReceived(). Jest to przydatne, gdy chcesz odszyfrować ładunek zaszyfrowany metodą end-to-end, dołączyć awatary użytkowników lub zlokalizować ciągi znaków.
Pamiętaj, aby uwzględnić obiekt notification w obiekcie remote_notification, nawet gdy mutable_content ma wartość true. GMS Core używa tego obiektu notification jako powiadomienia zastępczego, jeśli wywołanie zwrotne klienta przekroczy limit czasu lub limit blokowania.
Jeśli przeprowadzasz migrację ze starszych wiadomości z danymi w wersji 1 i chcesz, aby usługa FCM dostarczała ładunek do starszych instalacji klienta w wersji 1 jako czystą wiadomość z danymi, ustaw use_as_v1_data_message: true w remote_notification.
Przykładowy kod JSON pełnego żądania HTTP
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
}
}
}
}
}
Wyślij wiadomość BackgroundSync
Aby wysłać wiadomość, która nie jest pilna, na potrzeby synchronizacji danych w tle, aktualizacji stanu wyciszenia lub aktualizacji plakietki aplikacji bądź widżetu, użyj obiektu background_sync.
Nie używaj tych wiadomości do publikowania powiadomień widocznych dla użytkownika, ponieważ mogą one być grupowane lub opóźniane w celu optymalizacji czasu pracy na baterii.
Przykładowy kod JSON pełnego żądania HTTP
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": {}
}
}
}
Aktualizowanie wywołań zwrotnych klienta Androida
Aby otrzymywać wiadomości AndroidConfigV2 na Androidzie, zaktualizuj aplikację, aby korzystała z najnowszego pakietu SDK firebase-messaging. Zaktualizuj usługę rozszerzającą FirebaseMessagingService, implementując onNotificationReceived() i onBackgroundSyncReceived().
Instalowanie pakietu SDK EAP
W ramach programu wcześniejszego dostępu pakiet SDK firebase-messaging w wersji 2 jest rozpowszechniany jako lokalne archiwum repozytorium Maven, a nie przez publiczne repozytorium Maven Google.
Dodaj katalog
m2repositoryzawierający plikfirebase-messaging:26.1.0-eap01do katalogu głównego projektu aplikacji na Androida (<project-root>/m2repository), korzystając z jednej z tych opcji:- Opcja A. Pobierz gotowe archiwum: pobierz plik FirebaseMessaging_26.1.0-eap01.zip i wyodrębnij katalog
m2repositorydo katalogu głównego projektu na Androida (<project-root>/m2repository). Opcja B. Kompilowanie z GitHuba za pomocą Gradle: sklonuj gałąź
feature/fcm-android-config-v2-eaprepozytoriumfirebase/firebase-android-sdk, skompiluj lokalne repozytorium Maven i skopiuj wygenerowany katalogbuild/m2repositorydo katalogu głównego projektu aplikacji na Androida: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
- Opcja A. Pobierz gotowe archiwum: pobierz plik FirebaseMessaging_26.1.0-eap01.zip i wyodrębnij katalog
W pliku
settings.gradle.kts(lubsettings.gradle) na poziomie projektu dodaj lokalny katalogm2repositoryna początku blokurepositories, nadgoogle():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() } }W pliku
app/build.gradle.kts(lubapp/build.gradle) na poziomie modułu zaktualizuj zależnośćfirebase-messagingdo wersji26.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' }Zsynchronizuj projekt z plikami Gradle.
Obsługa RemoteNotifications za pomocą onNotificationReceived
Jeśli zasada AndroidConfigV2 jest ustawiona na RemoteNotification, komunikaty są wyświetlane, chyba że zasada mutable_content ma wartość Prawda lub komunikaty są wyciszone w zasadzie onNotificationReceived().
Gdy RemoteNotification dotrze z mutable_content: true, GMS Core wiąże się z Twoją aplikacją i wywołuje onNotificationReceived(). Metoda musi zwrócić NotificationResponse w ciągu 20 sekund.
Zwracanie zmodyfikowanego powiadomienia
Obiekt Notification przekazywany do metody NotificationResponse.create zastępuje właściwości zastępczych danych serwera remote_notification.notification zdefiniowane w żądaniu wysłania. Aby zachować wartości z żądania wysłania, odczytaj je z message.notification (message.getNotification() w języku Java) podczas stosowania modyfikacji na urządzeniu:
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());
}
}
Ukrywanie powiadomienia
Jeśli użytkownik ma obecnie aktywny odpowiedni ekran lub czat, możesz pominąć powiadomienie, zwracając 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());
}
Powiadomienia o transmisji lub anulowanie starszych alertów (FcmNotificationManager)
Jeśli chcesz opublikować kilka powiadomień dotyczących jednego przychodzącego powiadomienia push lub anulować nieaktualne powiadomienie przed wyświetleniem nowego, użyj 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();
}
Obsługuj wiadomości BackgroundSync za pomocą onBackgroundSyncReceived
Aby przetwarzać wiadomości BackgroundSync na Androidzie, użyj 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.
}
Obsługuj oczekujące usunięcia wiadomości za pomocą onDeletedMessages
W niektórych sytuacjach, na przykład gdy urządzenie nie połączyło się z FCM przez dłuższy czas lub gdy kolejka serwera jest pełna, FCM może usunąć oczekujące wiadomości przed ich dostarczeniem. W takich przypadkach zastąp 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();
}
Migracja określonych aplikacji
wysyłanie powiadomień z pełnym szyfrowaniem (E2EE);
Podczas dostarczania powiadomienia z pełnym szyfrowaniem za pomocą RemoteNotification odszyfrowana treść powiadomienia pozostaje w aplikacji i na platformie Androida:
- Dostarczanie powiadomienia, które można zmienić: Twój serwer wysyła
RemoteNotificationzmutable_content: true, zaszyfrowane dane wdatai ogólną niezaszyfrowaną kopię zapasowąnotification. GMS Core dostarcza zaszyfrowaną wiadomość do pakietu SDK FCM typu open source w Twojej aplikacji. - Odszyfrowanie i powiadomienie o zwrocie: pakiet SDK FCM wywołuje
onNotificationReceived(). Aplikacja odszyfrowuje ładunek lokalnie, tworzy ostateczny odszyfrowany obiektNotificationi przekazuje go z powrotem do pakietu SDK FCM o otwartym kodzie źródłowym za pomocąNotificationResponselubFcmNotificationManager. - Publikowanie na platformie i raportowanie metadanych: pakiet SDK FCM o otwartym kodzie źródłowym publikuje odszyfrowane powiadomienie bezpośrednio w interfejsie API
NotificationManagerplatformy Androida i wysyła do GMS Core tylko metadane powiadomienia, takie jak identyfikatory powiadomień i sygnatury czasowe, aby umożliwić obserwowanie dostarczania. Odszyfrowane treści nigdy nie są wysyłane do GMS Core. - W razie potrzeby opublikuj powiadomienie zapasowe: tylko wtedy, gdy aplikacja nie odpowie w ciągu 20 sekund lub przekroczy limity wyciszania w tle, GMS Core opublikuje ogólne powiadomienie zapasowe
notificationbezpośrednio na platformie Androida.

Omówienie blokowania powiadomień i czasu oczekiwania
Aby zapewnić niezawodne dostarczanie wiadomości w ekosystemie Androida, GMS Core stosuje limity czasu przetwarzania i limity blokowania powiadomień podczas obsługi wiadomości RemoteNotification:
Przekroczenie limitu czasu przetwarzania
Gdy właściwość mutable_content jest ustawiona na true, metoda onNotificationReceived() musi zwrócić NotificationResponse w ciągu 20 sekund. Jeśli czas wykonywania przekroczy ten próg, wywołanie zwrotne zostanie anulowane, a usługi GMS automatycznie opublikują powiadomienie zastępcze wygenerowane na podstawie danych remote_notification.notification.
Współczynnik pomijania powiadomień
Wiadomości RemoteNotification omijają ograniczenia trybu Doze, aby natychmiast powiadomić użytkowników, i są dostarczane bez opóźnień, dlatego aplikacje powinny wyświetlać powiadomienia o odebranych wiadomościach RemoteNotification.
Każda aplikacja może pominąć do 25% ruchu RemoteNotification, gdy działa w tle. Jeśli współczynnik pomijania aplikacji przekracza 25%, GMS Core automatycznie renderuje i publikuje powiadomienie zastępcze wyrenderowane z ładunku remote_notification.notification.
Blokady wykonywane, gdy aplikacja jest aktywna na pierwszym planie, nie wliczają się do tego progu. Aplikacje, którym przyznano uprawnienia do nieograniczonego użycia w tle, są również zwolnione z limitów dotyczących blokowania w tle.