Wysyłaj wiadomości do tematów w Unity

Wiadomości tematyczne oparte na modelu publikowania/subskrypcji umożliwiają wysyłanie wiadomościFCM do wielu urządzeń, które subskrybują dany temat. W razie potrzeby tworzysz wiadomości dotyczące tematu, a FCM zajmuje się routingiem i niezawodnym dostarczaniem wiadomości na odpowiednie urządzenia.

Na przykład użytkownicy lokalnej aplikacji do prognozowania pływów mogą włączyć temat „Alerty o prądach pływowych” i otrzymywać powiadomienia o optymalnych warunkach do połowów w określonych obszarach. Użytkownicy aplikacji sportowej mogą subskrybować automatyczne aktualizacje wyników meczów na żywo swoich ulubionych drużyn.

O tematach warto pamiętać o tych kwestiach:

  • Wiadomości dotyczące tematu najlepiej sprawdzają się w przypadku treści takich jak prognoza pogody lub inne informacje dostępne publicznie.
  • Wiadomości w tematach są optymalizowane pod kątem przepustowości, a nie opóźnienia. Aby szybko i bezpiecznie dostarczać wiadomości do pojedynczych urządzeń lub małych grup urządzeń, kieruj wiadomości na tokeny rejestracji, a nie na tematy.
  • Jeśli chcesz wysyłać wiadomości na wiele urządzeń każdego użytkownika, rozważ użycie wiadomości do grupy urządzeń.
  • Wiadomości tematyczne obsługują nieograniczoną liczbę subskrypcji każdego tematu. FCM egzekwuje jednak limity w tych obszarach:
    • Jedna instancja aplikacji może subskrybować maksymalnie 2000 tematów.
    • Jeśli do subskrybowania instancji aplikacji używasz importu zbiorczego, każde żądanie może zawierać maksymalnie 1000 instancji aplikacji.
    • Częstotliwość nowych subskrypcji jest ograniczona w przypadku każdego projektu. Jeśli w krótkim czasie wyślesz zbyt wiele żądań subskrypcji, serwery FCM odpowiedzą kodem 429 RESOURCE_EXHAUSTED („przekroczono limit”). Ponów próbę ze wzrastającym czasem do ponowienia.

Subskrybowanie tematu przez aplikację kliencką

Aby zasubskrybować temat, wywołaj Firebase.Messaging.FirebaseMessaging.Subscribe z aplikacji. Wysyła asynchroniczne żądanie do backendu FCMi subskrybuje klienta w danym temacie.

Firebase.Messaging.FirebaseMessaging.Subscribe("/topics/example");

Jeśli żądanie subskrypcji początkowo się nie powiedzie, FCM ponawia próby, dopóki nie uda się zasubskrybować tematu. Za każdym razem, gdy aplikacja się uruchamia, FCM sprawdza, czy wszystkie żądane tematy zostały zasubskrybowane.

Aby anulować subskrypcję, zadzwoń pod numer Firebase.Messaging.FirebaseMessaging.Unsubscribe.FCM anuluje subskrypcję tematu w tle.

Zarządzanie subskrypcjami tematów na serwerze

Interfejs Firebase Admin SDK umożliwia wykonywanie podstawowych zadań związanych z zarządzaniem tematami po stronie serwera. Na podstawie tokenów rejestracji możesz zbiorczo subskrybować i anulować subskrypcję instancji aplikacji klienckich za pomocą logiki serwera.

Możesz zasubskrybować instancje aplikacji klienckiej w dowolnym istniejącym temacie lub utworzyć nowy. Gdy używasz interfejsu API do subskrybowania aplikacji klienckiej nowego tematu (który nie istnieje jeszcze w Twoim projekcie Firebase), w FCM tworzony jest nowy temat o tej nazwie i każdy klient może go później zasubskrybować.

Możesz przekazać listę tokenów rejestracji do metody Firebase Admin SDKsubskrypcji, aby zasubskrybować odpowiednie urządzenia w temacie:

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Subscribe the devices corresponding to the registration tokens to the
// topic.
getMessaging().subscribeToTopic(registrationTokens, topic)
  .then((response) => {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully subscribed to topic:', response);
  })
  .catch((error) => {
    console.log('Error subscribing to topic:', error);
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Subscribe the devices corresponding to the registration tokens to the
// topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were subscribed successfully");

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Subscribe the devices corresponding to the registration tokens to the
# topic.
response = messaging.subscribe_to_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were subscribed successfully')

Go

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Subscribe the devices corresponding to the registration tokens to the
// topic.
response, err := client.SubscribeToTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were subscribed successfully")

C#

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};

// Subscribe the devices corresponding to the registration tokens to the
// topic
var response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were subscribed successfully");

Interfejs Admin FCM API umożliwia też anulowanie subskrypcji urządzenia w temacie przez przekazanie tokenów rejestracji do odpowiedniej metody:

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
getMessaging().unsubscribeFromTopic(registrationTokens, topic)
  .then((response) => {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully unsubscribed from topic:', response);
  })
  .catch((error) => {
    console.log('Error unsubscribing from topic:', error);
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().unsubscribeFromTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were unsubscribed successfully");

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Unubscribe the devices corresponding to the registration tokens from the
# topic.
response = messaging.unsubscribe_from_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were unsubscribed successfully')

Go

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
response, err := client.UnsubscribeFromTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were unsubscribed successfully")

C#

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};

// Unsubscribe the devices corresponding to the registration tokens from the
// topic
var response = await FirebaseMessaging.DefaultInstance.UnsubscribeFromTopicAsync(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were unsubscribed successfully");
.

Metody subscribeToTopic() i unsubscribeFromTopic() zwracają obiekt zawierający odpowiedź z FCM. Typ zwracany ma taki sam format niezależnie od liczby tokenów rejestracyjnych podanych w żądaniu.

W przypadku błędu (nieudane uwierzytelnienie, nieprawidłowy token lub temat itp.) te metody zwracają błąd. Pełną listę kodów błędów wraz z opisami i krokami rozwiązywania problemów znajdziesz w artykule Błędy interfejsu Admin FCM API.

Odbieranie i obsługa wiadomości dotyczących tematu

FCM dostarcza wiadomości o tematach w taki sam sposób jak inne wiadomości wysyłane do urządzenia.

Subskrybując zdarzenie Firebase.Messaging.FirebaseMessaging.MessageReceived, możesz wykonywać działania na podstawie otrzymanej wiadomości i pobierać dane wiadomości.

Firebase.Messaging.FirebaseMessaging.MessageReceived += OnMessageReceived;

...

public void OnMessageReceived(object sender, Firebase.Messaging.MessageReceivedEventArgs e) {
  UnityEngine.Debug.Log("Received a new message");
  if (e.Message.From.Length > 0)
    UnityEngine.Debug.Log("from: " + e.Message.From);
  if (e.Message.Data.Count > 0) {
    UnityEngine.Debug.Log("data:");
    foreach (System.Collections.Generic.KeyValuePair<string, string> iter in
             e.Message.Data) {
      UnityEngine.Debug.Log("  " + iter.Key + ": " + iter.Value);
    }
  }
}

Tworzenie próśb o wysłanie

Po utworzeniu tematu (przez subskrybowanie instancji aplikacji klienckiej w temacie po stronie klienta lub za pomocą interfejsu API serwera) możesz wysyłać do niego wiadomości. Jeśli po raz pierwszy tworzysz żądania wysyłania dla FCM, zapoznaj się z przewodnikiem dotyczącym środowiska serwera i FCM, aby uzyskać ważne informacje o konfiguracji i kontekście.

W logice wysyłania na backendzie określ nazwę tematu w sposób pokazany poniżej:

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

Java

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

Python

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

Go

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

REST

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, czyli wyrażenie logiczne, które określa docelowe tematy. Na przykład ten warunek spowoduje wysłanie wiadomości na urządzenia, które subskrybują TopicA oraz TopicB lub TopicC:

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

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

  • TopicA i TopicB
  • TopicA i TopicC

W wyrażeniu warunkowym możesz uwzględnić maksymalnie 5 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);
  });

Java

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

Python

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

Go

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

REST

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