Há duas maneiras de enviar uma mensagem para vários dispositivos usando o Firebase Cloud Messaging:
- Mensagens de tópicos, que permitem o envio de uma mensagem a vários dispositivos que optaram por receber mensagens sobre um tópico específico.
- Mensagens para grupos de dispositivos, que enviam uma única mensagem a várias instâncias de um app executado em dispositivos de um mesmo grupo.
O objetivo deste tutorial é mostrar o envio de mensagens de tópicos do servidor do app usando o SDK Admin ou a API REST para FCM, além de receber e processar essas mensagens em um app da Apple. Esta página contém todas as etapas do procedimento, desde a configuração até a verificação. Portanto, ela pode abranger as etapas que você já concluiu se tiver configurado um app cliente da Apple para o FCM ou executado as etapas para Enviar sua primeira mensagem.
Adicionar o Firebase ao projeto da Apple
Esta seção aborda tarefas que você talvez tenha realizado se já ativou outros recursos do Firebase no app. Especificamente para o FCM, você precisa fazer upload da chave de autenticação dos APNs e registrar o app para receber notificações remotas.
Pré-requisitos
Instale o seguinte:
- Xcode 14.1 ou versões mais recentes
Verifique se o projeto atende a estes requisitos:
- O projeto precisa ser direcionado a estas versões da plataforma ou versões mais recentes:
- iOS 11
- macOS 10.13
- tvOS 12
- watchOS 6
- O projeto precisa ser direcionado a estas versões da plataforma ou versões mais recentes:
Configure um dispositivo Apple físico para executar o app e concluir estas tarefas:
- Conseguir uma chave de autenticação de notificação push da Apple para sua conta do Apple Developer.
- Ativar as notificações push no Xcode em App > Capabilities.
- Faça login no Firebase usando a conta do Google.
Se você ainda não tem um projeto do Xcode e quer testar um produto do Firebase, faça o download de uma das nossas amostras introdutórias.
Criar um projeto do Firebase
Antes de adicionar o Firebase ao seu app da Apple, crie um projeto do Firebase para conectá-lo ao app. Acesse Noções básicas sobre projetos do Firebase para saber mais.
Registrar o app no Firebase
Para usar o Firebase no seu app da Apple, é necessário registrá-lo no projeto do Firebase. Registrar o app também quer dizer "adicionar" o app ao projeto.
Acesse o Console do Firebase.
No centro da página de visão geral do projeto, clique no ícone iOS+ para iniciar o fluxo de trabalho de configuração.
Se você já adicionou um app ao seu projeto do Firebase, clique em Adicionar app para exibir as opções da plataforma.
Insira o ID do pacote do seu app no campo ID do pacote.
(Opcional) Insira outras informações do aplicativo: apelido do aplicativo e ID da App Store.
Clique em Registrar app.
Adicionar um arquivo de configuração do Firebase
Clique em Fazer o download do GoogleService-Info.plist para solicitar o arquivo de configuração do Firebase para plataformas Apple (
GoogleService-Info.plist
).Mova o arquivo de configuração para a raiz do seu projeto XCode. Se solicitado, selecione a opção para adicionar o arquivo de configuração a todos os destinos.
Se o projeto tiver vários IDs de pacotes, associe cada ID
a um app registrado no Console do Firebase para que tenha
o próprio arquivo GoogleService-Info.plist
.
Adicionar SDKs do Firebase ao seu app
Use o Swift Package Manager para instalar e gerenciar as dependências do Firebase.
- No Xcode, com seu projeto do app aberto, navegue até File > Add Packages.
- Quando solicitado, adicione o repositório do SDK do Firebase para as plataformas Apple:
- Escolha a biblioteca do Firebase Cloud Messaging.
- Para uma experiência ideal com o Firebase Cloud Messaging, recomendamos ativar o Google Analytics no projeto do Firebase e adicionar o SDK do Firebase para Analytics ao seu app. Você pode selecionar a biblioteca com ou sem o recurso de coleta de IDFAs.
- Quando terminar, o Xcode começará a resolver e fazer o download das dependências em segundo plano automaticamente.
https://github.com/firebase/firebase-ios-sdk
Fazer upload da chave de autenticação de APNs
Faça upload da chave de autenticação de APNs para o Firebase. Se você ainda não tiver uma chave de autenticação de APNs, crie uma no Apple Developer Member Center.
-
No seu projeto no Console do Firebase, selecione o ícone de engrenagem, Configurações do projeto e a guia Cloud Messaging.
-
Acesse a Configuração do app iOS. Em Chave de autenticação de APNs, clique no botão Fazer upload.
-
Navegue até o local onde você salvou a chave, selecione-a e clique em Abrir. Adicione o ID da chave disponível no Apple Developer Member Center e clique em Fazer upload.
Inicializar o Firebase no seu app
É necessário adicionar o código de inicialização do Firebase ao seu app. Importe o módulo do Firebase e configure uma instância compartilhada da seguinte maneira:
- Importe o módulo
FirebaseCore
noUIApplicationDelegate
, assim como qualquer outro módulo do Firebase usado pelo delegado do app. Por exemplo, para usar o Cloud Firestore e o Authentication:SwiftUI
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Swift
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objective-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- Configure uma
instância compartilhada do
FirebaseApp
no métodoapplication(_:didFinishLaunchingWithOptions:)
do delegado do app:SwiftUI
// Use Firebase library to configure APIs FirebaseApp.configure()
Swift
// Use Firebase library to configure APIs FirebaseApp.configure()
Objective-C
// Use Firebase library to configure APIs [FIRApp configure];
- Se você estiver usando a SwiftUI, crie um delegado do aplicativo e o anexe
ao struct
App
viaUIApplicationDelegateAdaptor
ouNSApplicationDelegateAdaptor
. Também é necessário desativar o swizzling do delegado do app. Para mais informações, consulte as instruções da SwiftUI.SwiftUI
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
Registrar o app para receber notificações remotas
Na inicialização ou no ponto desejado do fluxo do seu aplicativo, registre-o para receber notificações remotas. ChameregisterForRemoteNotifications
conforme mostrado:
Swift
UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: { _, _ in } ) application.registerForRemoteNotifications()
Objective-C
[UNUserNotificationCenter currentNotificationCenter].delegate = self; UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge; [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) { // ... }]; [application registerForRemoteNotifications];
Inscrever o app cliente em um tópico
Os apps clientes podem ser inscritos em qualquer tópico atual ou podem criar um novo tópico. Quando um app cliente for inscrito em um novo nome de tópico que ainda não existe no seu projeto do Firebase, um novo tópico com esse nome será criado no FCM e qualquer cliente poderá se inscrever nele posteriormente.
Para se inscrever em um tópico, chame o método de inscrição na thread principal do seu aplicativo. O FCM não é thread-safe, ou seja, não está pronto para ter uma instância utilizada entre várias threads simultaneamente. Se a solicitação de inscrição falhar, o FCM vai repetir a tentativa automaticamente. Nos casos em que a inscrição não pode ser concluída, ela emite um erro que você captura em um manipulador de conclusão, conforme mostrado abaixo:
Swift
Messaging.messaging().subscribe(toTopic: "weather") { error in print("Subscribed to weather topic") }
Objective-C
[[FIRMessaging messaging] subscribeToTopic:@"weather" completion:^(NSError * _Nullable error) { NSLog(@"Subscribed to weather topic"); }];
Essa chamada faz uma
solicitação assíncrona ao back-end do FCM e inscreve o cliente no
tópico. Antes de chamar subscribeToTopic:topic
, use o retorno de chamada didReceiveRegistrationToken
para conferir se a
instância do app cliente já recebeu um token de registro.
Sempre que o app é iniciado,
o FCM verifica a inscrição em todos os tópicos solicitados. Para cancelar a inscrição, chame unsubscribeFromTopic:topic
para que o FCM faça o cancelamento em segundo plano.
Receber e processar mensagens de tópicos
O FCM entrega as mensagens de tópicos da mesma maneira que as outras mensagens downstream.
Implemente application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
como mostrado:
Swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async -> UIBackgroundFetchResult { // If you are receiving a notification message while your app is in the background, // this callback will not be fired till the user taps on the notification launching the application. // TODO: Handle data of notification // With swizzling disabled you must let Messaging know about the message, for Analytics // Messaging.messaging().appDidReceiveMessage(userInfo) // Print message ID. if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: \(messageID)") } // Print full message. print(userInfo) return UIBackgroundFetchResult.newData }
Objective-C
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // If you are receiving a notification message while your app is in the background, // this callback will not be fired till the user taps on the notification launching the application. // TODO: Handle data of notification // With swizzling disabled you must let Messaging know about the message, for Analytics // [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; // ... // Print full message. NSLog(@"%@", userInfo); completionHandler(UIBackgroundFetchResultNewData); }
Criar solicitações de envio
Depois de criar um tópico, seja inscrevendo instâncias do app cliente no tópico do lado do cliente ou usando a API do servidor, será possível enviar mensagens ao tópico. Se esta for a primeira vez que você cria solicitações de envio para o FCM, consulte o guia do ambiente do servidor e o FCM para informações gerais importantes e sobre configuração.
Na sua lógica de envio no back-end, especifique o nome do tópico desejado conforme mostrado abaixo:
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"
}
}
}
Comando 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
Para enviar uma mensagem para uma combinação de tópicos,
especifique uma condição, que é uma expressão booleana que especifica os
tópicos de destino. Por exemplo, a seguinte condição vai enviar mensagens para
dispositivos que estão inscritos em TopicA
e TopicB
ou TopicC
:
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"
No FCM, todas as condições entre parênteses são avaliadas primeiro e depois a
expressão é analisada da esquerda para a direita. Na expressão acima, um usuário que se inscreveu em um
só tópico não receberá a mensagem. Do mesmo modo, um usuário que não
se inscreveu em TopicA
também não receberá a mensagem. Somente estas combinações
são válidas:
TopicA
eTopicB
TopicA
eTopicC
Você pode incluir até cinco tópicos na sua expressão condicional.
Para enviar para uma condição:
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",
}
}
}
Comando 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
Próximas etapas
- Você pode usar seu servidor para inscrever instâncias de apps clientes em tópicos e realizar outras tarefas de gerenciamento. Consulte Gerenciar inscrições em tópicos no servidor.
- Saiba mais sobre outras maneiras de enviar mensagens a vários dispositivos em Mensagens para grupos de dispositivos.