Wysyłaj wiadomości do wielu urządzeń

Aby kierować wiadomość do wielu urządzeń, użyj Wiadomości tematycznych . Ta funkcja umożliwia wysłanie wiadomości do wielu urządzeń, które wybrały określony temat.

W tym samouczku skupiono się na wysyłaniu komunikatów tematycznych z serwera aplikacji przy użyciu zestawu Admin SDK lub interfejsu API REST dla FCM oraz odbieraniu ich i obsłudze w aplikacji na Androida. Omówimy obsługę wiadomości zarówno w aplikacjach działających w tle, jak i na pierwszym planie. Omówiono wszystkie kroki, aby to osiągnąć, od konfiguracji po weryfikację.

Skonfiguruj pakiet SDK

Ta sekcja może obejmować kroki, które już wykonałeś, jeśli skonfigurowałeś aplikację kliencką dla systemu Android dla FCM lub wykonałeś kroki, aby wysłać pierwszą wiadomość .

Zanim zaczniesz

  • Zainstaluj lub zaktualizuj Android Studio do najnowszej wersji.

  • Upewnij się, że Twój projekt spełnia następujące wymagania:

    • Docelowy poziom API 19 (KitKat) lub wyższy
    • Używa Androida 4.4 lub nowszego
    • Korzysta z Jetpack (AndroidX) , co obejmuje spełnienie następujących wymagań wersji:
      • com.android.tools.build:gradle w wersji 7.3.0 lub nowszej
      • compileSdkVersion 28 lub nowsza
  • Skonfiguruj urządzenie fizyczne lub użyj emulatora , aby uruchomić aplikację.
    Pamiętaj, że zestawy SDK Firebase zależne od usług Google Play wymagają, aby na urządzeniu lub emulatorze były zainstalowane usługi Google Play.

  • Zaloguj się do Firebase przy użyciu swojego konta Google.

Jeśli nie masz jeszcze projektu na Androida i chcesz po prostu wypróbować produkt Firebase, możesz pobrać jeden z naszych przykładów szybkiego startu .

Utwórz projekt Firebase

Zanim będziesz mógł dodać Firebase do swojej aplikacji na Androida, musisz utworzyć projekt Firebase, aby połączyć się z tą aplikacją na Androida. Odwiedź stronę Poznaj projekty Firebase, aby dowiedzieć się więcej o projektach Firebase.

Zarejestruj swoją aplikację w Firebase

Aby korzystać z Firebase w aplikacji na Androida, musisz zarejestrować aplikację w projekcie Firebase. Rejestracja aplikacji jest często nazywana „dodawaniem” aplikacji do projektu.

  1. Przejdź do konsoli Firebase .

  2. Na środku strony przeglądu projektu kliknij ikonę Androida ( ) lub Dodaj aplikację , aby uruchomić proces konfiguracji.

  3. Wpisz nazwę pakietu aplikacji w polu nazwy pakietu Androida .

  4. (Opcjonalnie) Wprowadź inne informacje o aplikacji: pseudonim aplikacji i certyfikat podpisywania debugowania SHA-1 .

  5. Kliknij opcję Zarejestruj aplikację .

Dodaj plik konfiguracyjny Firebase

  1. Pobierz, a następnie dodaj plik konfiguracyjny Firebase Android ( google-services.json ) do swojej aplikacji:

    1. Kliknij Pobierz plik google-services.json, aby uzyskać plik konfiguracyjny Firebase na Androida.

    2. Przenieś plik konfiguracyjny do katalogu głównego modułu (na poziomie aplikacji) swojej aplikacji.

  2. Aby wartości w pliku konfiguracyjnym google-services.json były dostępne dla zestawów SDK Firebase, potrzebujesz wtyczki Gradle usług Google ( google-services ).

    1. W pliku Gradle na poziomie głównym (na poziomie projektu) ( <project>/build.gradle.kts lub <project>/build.gradle ) dodaj wtyczkę usług Google jako zależność:

      Kotlin

      plugins {
        id("com.android.application") version "7.3.0" apply false
        // ...
      
        // Add the dependency for the Google services Gradle plugin
        id("com.google.gms.google-services") version "4.4.1" apply false
      }
      

      Groovy

      plugins {
        id 'com.android.application' version '7.3.0' apply false
        // ...
      
        // Add the dependency for the Google services Gradle plugin
        id 'com.google.gms.google-services' version '4.4.1' apply false
      }
      
    2. W pliku Gradle modułu (na poziomie aplikacji) (zwykle <project>/<app-module>/build.gradle.kts lub <project>/<app-module>/build.gradle ) dodaj wtyczkę usług Google:

      Kotlin

      plugins {
        id("com.android.application")
      
        // Add the Google services Gradle plugin
        id("com.google.gms.google-services")
        // ...
      }
      

      Groovy

      plugins {
        id 'com.android.application'
      
        // Add the Google services Gradle plugin
        id 'com.google.gms.google-services'
        // ...
      }
      

Dodaj pakiety SDK Firebase do swojej aplikacji

  1. W pliku Gradle modułu (na poziomie aplikacji) (zwykle <project>/<app-module>/build.gradle.kts lub <project>/<app-module>/build.gradle ) dodaj zależność dla chmury Firebase Biblioteka wiadomości dla Androida. Zalecamy używanie Firebase Android BoM do kontrolowania wersji bibliotek.

    Aby zapewnić optymalne działanie Firebase Cloud Messaging, zalecamy włączenie Google Analytics w projekcie Firebase i dodanie pakietu SDK Firebase dla Google Analytics do swojej aplikacji.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:32.8.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")
    }
    

    Korzystając z Firebase Android BoM , Twoja aplikacja będzie zawsze korzystać z kompatybilnych wersji bibliotek Firebase Android.

    (Alternatywa) Dodaj zależności biblioteki Firebase bez użycia BoM

    Jeśli zdecydujesz się nie używać BoM Firebase, musisz określić każdą wersję biblioteki Firebase w jej wierszu zależności.

    Pamiętaj, że jeśli używasz w swojej aplikacji wielu bibliotek Firebase, zdecydowanie zalecamy używanie BoM do zarządzania wersjami bibliotek, co gwarantuje, że wszystkie wersje będą kompatybilne.

    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.4.1")
        implementation("com.google.firebase:firebase-analytics:21.6.1")
    }
    
    Szukasz modułu bibliotecznego specyficznego dla Kotlina? Począwszy od października 2023 r. (Firebase BoM 32.5.0) zarówno programiści Kotlin, jak i Java mogą polegać na głównym module biblioteki (więcej informacji można znaleźć w często zadawanych pytaniach dotyczących tej inicjatywy ).

  2. Zsynchronizuj swój projekt na Androida z plikami Gradle.

Subskrybuj aplikację kliencką do tematu

Aplikacje klienckie mogą subskrybować dowolny istniejący temat lub utworzyć nowy temat. Kiedy aplikacja kliencka subskrybuje nową nazwę tematu (taką, która jeszcze nie istnieje w Twoim projekcie Firebase), w FCM tworzony jest nowy temat o tej nazwie i każdy klient może go następnie zasubskrybować.

Aby zasubskrybować temat, aplikacja kliencka wywołuje funkcję Firebase Cloud Messaging subscribeToTopic() z nazwą tematu FCM. Ta metoda zwraca Task , którego może użyć słuchacz zakończenia w celu ustalenia, czy subskrypcja się powiodła:

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();
            }
        });

Aby anulować subskrypcję, aplikacja kliencka wywołuje funkcję Firebase Cloud Messaging unsubscribeFromTopic() z nazwą tematu.

Odbieraj i obsługuj wiadomości tematyczne

FCM dostarcza wiadomości tematyczne w taki sam sposób, jak inne wiadomości niższego szczebla.

Aby odbierać wiadomości, użyj usługi rozszerzającej FirebaseMessagingService . Twoja usługa powinna zastąpić wywołania zwrotne onMessageReceived i onDeletedMessages .

Okno czasowe na obsługę wiadomości może być krótsze niż 20 sekund w zależności od opóźnień powstałych przed wywołaniem onMessageReceived , w tym opóźnień systemu operacyjnego, czasu uruchamiania aplikacji, zablokowania głównego wątku przez inne operacje lub poprzednich wywołań onMessageReceived trwających zbyt długo. Po tym czasie różne zachowania systemu operacyjnego, takie jak zabijanie procesów w systemie Android lub limity wykonywania w tle w systemie Android O, mogą zakłócać możliwość ukończenia pracy.

onMessageReceived jest dostępny dla większości typów wiadomości, z następującymi wyjątkami:

  • Powiadomienia dostarczane, gdy aplikacja działa w tle . W takim przypadku powiadomienie jest dostarczane do zasobnika systemowego urządzenia. Dotknięcie powiadomienia przez użytkownika domyślnie otwiera program uruchamiający aplikacje.

  • Wiadomości zawierające zarówno powiadomienia, jak i dane, odbierane w tle . W takim przypadku powiadomienie jest dostarczane do zasobnika systemowego urządzenia, a ładunek danych jest dostarczany w ramach dodatków do aktywności programu uruchamiającego.

W podsumowaniu:

Stan aplikacji Powiadomienie Dane Obydwa
Pierwszoplanowy onMessageReceived onMessageReceived onMessageReceived
Tło Taca systemowa onMessageReceived Powiadomienie: zasobnik systemowy
Dane: w dodatkach intencji.
Aby uzyskać więcej informacji na temat typów wiadomości, zobacz Powiadomienia i wiadomości dotyczące danych .

Edytuj manifest aplikacji

Aby korzystać z FirebaseMessagingService , musisz dodać następujące informacje w manifeście aplikacji:

<service
    android:name=".java.MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

Zaleca się także ustawienie wartości domyślnych w celu dostosowania wyglądu powiadomień. Można określić niestandardową ikonę domyślną i niestandardowy domyślny kolor, które będą stosowane, gdy w ładunku powiadomienia nie zostaną ustawione równoważne wartości.

Dodaj te linie wewnątrz znacznika application , aby ustawić niestandardową domyślną ikonę i niestandardowy kolor:

<!-- 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 wyświetla niestandardową domyślną ikonę dla

Android używa niestandardowego domyślnego koloru dla

Jeśli nie ustawiono żadnej niestandardowej ikony domyślnej ani w ładunku powiadomienia, system Android wyświetla ikonę aplikacji renderowaną na biało.

Zastąp onMessageReceived

Nadpisując metodę FirebaseMessagingService.onMessageReceived , możesz wykonać akcje na podstawie odebranego obiektu RemoteMessage i uzyskać dane komunikatu:

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.
}

Zastąp onDeletedMessages

W niektórych sytuacjach FCM może nie dostarczyć wiadomości. Dzieje się tak, gdy w momencie nawiązania połączenia na określonym urządzeniu znajduje się zbyt wiele wiadomości (>100) oczekujących dla Twojej aplikacji lub jeśli urządzenie nie łączyło się z FCM przez ponad miesiąc. W takich przypadkach możesz otrzymać wywołanie zwrotne do FirebaseMessagingService.onDeletedMessages() . Gdy instancja aplikacji odbierze to wywołanie zwrotne, powinna przeprowadzić pełną synchronizację z serwerem aplikacji. Jeśli w ciągu ostatnich 4 tygodni nie wysłałeś wiadomości do aplikacji na tym urządzeniu, FCM nie wywoła onDeletedMessages() .

Obsługuj powiadomienia w aplikacji działającej w tle

Gdy aplikacja działa w tle, Android kieruje powiadomienia do paska zadań. Dotknięcie powiadomienia przez użytkownika domyślnie otwiera program uruchamiający aplikacje.

Obejmuje to wiadomości zawierające zarówno powiadomienia, jak i ładunek danych (oraz wszystkie wiadomości wysłane z konsoli powiadomień). W takich przypadkach powiadomienie jest dostarczane do zasobnika systemowego urządzenia, a ładunek danych jest dostarczany w ramach dodatków do Aktywności programu uruchamiającego.

Wgląd w dostarczanie wiadomości do aplikacji znajdziesz w panelu raportowania FCM , który rejestruje liczbę wiadomości wysłanych i otwartych na urządzeniach Apple i Android, wraz z danymi dotyczącymi „wyświetleń” (powiadomień widocznych przez użytkowników) w przypadku aplikacji na Androida.

Twórz żądania wysyłania

Po utworzeniu tematu, subskrybując instancje aplikacji klienckiej do tematu po stronie klienta lub za pośrednictwem interfejsu API serwera , możesz wysyłać wiadomości do tematu. Jeśli tworzysz żądania wysyłania dla FCM po raz pierwszy, zapoznaj się z przewodnikiem po środowisku serwera i FCM , aby uzyskać ważne informacje dotyczące tła i konfiguracji.

W logice wysyłania na zapleczu określ żądaną nazwę tematu, jak pokazano:

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);
  });

Jawa

// 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);

Pyton

# 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)

Iść

// 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)

C#

// 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);

ODPOCZYNEK

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"
      }
   }
}

polecenie curl:

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

Aby wysłać wiadomość do kombinacji tematów, określ warunek , który jest wyrażeniem boolowskim określającym tematy docelowe. Na przykład następujący warunek wyśle ​​wiadomości do urządzeń subskrybujących TopicA oraz TopicB lub TopicC :

"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"

FCM najpierw ocenia wszystkie warunki w nawiasach, a następnie ocenia wyrażenie od lewej do prawej. W powyższym wyrażeniu użytkownik subskrybujący dowolny temat nie otrzymuje wiadomości. Podobnie użytkownik, który nie subskrybuje TopicA nie otrzyma wiadomości. Te kombinacje go otrzymują:

  • TopicA i TopicB
  • TopicA i TopicC

W wyrażeniu warunkowym możesz uwzględnić maksymalnie pięć tematów.

Aby wysłać do warunku:

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);
  });

Jawa

// 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);

Pyton

# 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)

Iść

// 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)

C#

// 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);

ODPOCZYNEK

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",
    }
  }
}

polecenie curl:

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

Następne kroki