Ir para o console

Enviar mensagens para vários dispositivos no iOS

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.

Este é um tutorial sobre como enviar mensagens de tópico do seu servidor de apps usando os protocolos HTTP ou XMPP para o FCM, e como receber e processar essas mensagens em um app para iOS. Veja nesta página todas as etapas para fazer isso, desde a configuração até a verificação. Se você configurou um app cliente para iOS no FCM ou enviou sua primeira mensagem, talvez algumas etapas abordadas nesta seção já tenham sido concluídas.

Adicionar o Firebase ao seu projeto para iOS

Se você já ativou outros recursos do Firebase para seu app, é provável que tenha concluído as tarefas abordadas nesta seção. Especificamente para o FCM, será necessário fazer upload da chave de autenticação de APNs e registrar o app para receber notificações remotas.

Pré-requisitos

Antes de começar, é preciso configurar o ambiente com o seguinte:

  • Xcode 10.1 ou versões posteriores
  • Um projeto do Xcode segmentado para iOS 8 ou versões posteriores
  • Para projetos do Swift, Swift 3.0 ou posterior
  • O identificador de pacote do seu app
  • CocoaPods 1.4.0 ou posterior
  • Para Cloud Messaging:
    • Um dispositivo físico com iOS
    • Uma chave de autenticação de notificação push da Apple para sua conta de desenvolvedor da Apple
    • No Xcode, ative as notificações push em App > Recursos

Se você ainda não tem um projeto do Xcode e quer apenas testar um recurso do Firebase, pode fazer o download de um de nossos exemplos para início rápido. Caso use um exemplo para início rápido, anote o identificador do pacote nas configurações do projeto. Você precisará dele na próxima etapa.

Adicionar o Firebase ao app

Adicione o Firebase ao seu app. Para isso, serão necessários um projeto e um arquivo de configuração do Firebase para o aplicativo. Se você quiser mais informações, consulte Noções básicas sobre projetos do Firebase.

Agora que você tem um projeto, adicione seu app para iOS a ele:

  1. Clique em Adicionar o Firebase ao app para iOS e siga as etapas de configuração. Se você estiver importando um projeto do Google, isso poderá ocorrer automaticamente. Basta fazer o download do arquivo de configuração.

  2. Quando solicitado, digite o código do pacote do app. É importante inserir essa informação ao adicionar um app ao projeto do Firebase.

  3. Adicione o arquivo de configuração do Firebase para iOS ao app:

    1. Clique em Fazer o download do GoogleService-Info.plist para receber o arquivo de configuração do Firebase para iOS (GoogleService-Info.plist).

      É possível fazer o download do arquivo de configuração do Firebase para iOS novamente a qualquer momento.

    2. Mova o arquivo de configuração para a raiz do seu projeto Xcode. Quando solicitado, selecione a opção para adicionar o arquivo de configuração a todos os destinos.

  4. Depois de adicionar o código de inicialização, execute seu app para enviar ao Console a confirmação de que você instalou o Firebase com sucesso.

Consulte Noções básicas sobre projetos do Firebase para ver práticas recomendadas e informações sobre como adicionar apps a um projeto, incluindo como lidar com diversas variantes de criação.

Adicionar o SDK

Se você estiver configurando um novo projeto, é necessário instalar o SDK. Talvez você tenha feito isso durante a criação do projeto do Firebase.

Recomendamos o uso do CocoaPods para a instalação das bibliotecas. Você pode instalar o CocoaPods seguindo as instruções de instalação (em inglês). Se você prefere não usar o CocoaPods, é possível integrar as bibliotecas do SDK diretamente sem precisar dele.

Se você fizer o download e executar um dos exemplos de guia de início rápido, o projeto do Xcode e o Podfile já estarão adicionados, mas você ainda precisará instalar os pods e fazer o download do arquivo GoogleService-Info.plist. Se quiser integrar as bibliotecas do Firebase a um de seus projetos, adicione os pods das bibliotecas que quer usar.

  1. Se você ainda não tiver um projeto do Xcode, crie um agora.

  2. Crie um Podfile se ainda não tiver um:

    $ cd your-project directory
    $ pod init
    
  3. Inclua os pods que quer instalar. Você pode incluir um pod em seu Podfile como este:

    pod 'Firebase/Analytics'
    pod 'Firebase/Messaging'
    

    Esse procedimento adicionará as bibliotecas de pré-requisitos necessárias para colocar o Firebase em funcionamento no seu aplicativo para iOS, juntamente com o Google Analytics para Firebase. Os pods e as subespecificações disponíveis no momento estão listados a seguir. Essas informações também estão nos guias de configuração específicos dos recursos.

  4. Instale os pods e abra o arquivo .xcworkspace para ver o projeto no Xcode.

    $ pod install
    $ open your-project.xcworkspace
    
  5. Faça o download de um arquivo GoogleService-Info.plist no Console do Firebase e inclua-o no seu app.

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 tem uma chave de autenticação de APNs, consulte Configurar APNs com o FCM.

  1. No seu projeto do Console do Firebase, selecione o ícone de engrenagem, Configurações do projeto e a guia Cloud Messaging.

  2. Acesse a Configuração do app para iOS. Em Chave de autenticação de APNs, clique no botão Upload.

  3. Navegue até o local onde você salvou a chave, selecione-a e clique em Abrir. Adicione o código da chave, disponível na seção Certificates, Identifiers & Profiles no Apple Developer Member Center (em inglês), e clique em 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:

  1. Importe o módulo do Firebase no UIApplicationDelegate:

    Swift

    import Firebase
    

    Objective-C

    @import Firebase;
    
  2. Configure uma instância compartilhada do FirebaseApp, que é normalmente encontrada no método application:didFinishLaunchingWithOptions: do aplicativo:

    Swift

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    Objective-C

    // Use Firebase library to configure APIs
    [FIRApp configure];

Registrar o app para receber notificações remotas

Na inicialização ou no ponto desejado do fluxo do seu app, registre-o para receber notificações remotas. Chame o registerForRemoteNotifications da seguinte maneira:

Swift

if #available(iOS 10.0, *) {
  // For iOS 10 display notification (sent via APNS)
  UNUserNotificationCenter.current().delegate = self

  let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
  UNUserNotificationCenter.current().requestAuthorization(
    options: authOptions,
    completionHandler: {_, _ in })
} else {
  let settings: UIUserNotificationSettings =
  UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
  application.registerUserNotificationSettings(settings)
}

application.registerForRemoteNotifications()

Objective-C

if ([UNUserNotificationCenter class] != nil) {
  // iOS 10 or later
  // For iOS 10 display notification (sent via APNS)
  [UNUserNotificationCenter currentNotificationCenter].delegate = self;
  UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
      UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
  [[UNUserNotificationCenter currentNotificationCenter]
      requestAuthorizationWithOptions:authOptions
      completionHandler:^(BOOL granted, NSError * _Nullable error) {
        // ...
      }];
} else {
  // iOS 10 notifications aren't available; fall back to iOS 8-9 notifications.
  UIUserNotificationType allNotificationTypes =
  (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
  UIUserNotificationSettings *settings =
  [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
  [application registerUserNotificationSettings:settings];
}

[application registerForRemoteNotifications];

Inscrever o app cliente em um tópico

Os apps cliente podem ser inscritos em qualquer tópico existente ou podem criar um novo tópico. Quando um app cliente se inscreve 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. Lembre-se de que o FCM não é thread-safe. Se a solicitação de inscrição falhar, o FCM repetirá a tentativa automaticamente. Nos casos em que a inscrição não pode ser concluída, ela emite um erro que você pode capturar 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 cria uma solicitação assíncrona ao back-end do FCM e inscreve o cliente no tópico. Antes de chamar o subscribeToTopic:topic, verifique se a instância do app cliente já recebeu um token de registro por meio do retorno de chamada didReceiveRegistrationToken.

Sempre que o app for iniciado, o FCM garantirá que todos os tópicos solicitados estejam inscritos. Se você quiser cancelar a inscrição, chame unsubscribeFromTopic:topic para que o FCM cancele a inscrição do tópico em segundo plano.

Receber e processar mensagens de tópico

O FCM entrega as mensagens de tópico da mesma maneira que as outras mensagens downstream.

Implemente AppDelegate application:didReceiveRemoteNotification: como mostrado:

Swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
  // 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)
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  // 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)

  completionHandler(UIBackgroundFetchResult.newData)
}

Objective-C

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
  // 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 message ID.
  if (userInfo[kGCMMessageIDKey]) {
    NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
  }

  // Print full message.
  NSLog(@"%@", userInfo);
}

- (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 message ID.
  if (userInfo[kGCMMessageIDKey]) {
    NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
  }

  // 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 para o tópico no cliente ou por meio da API do servidor, será possível enviar mensagens a ele. 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/".
var topic = 'highScores';

var message = {
  data: {
    score: '850',
    time: '2:45'
  },
  topic: topic
};

// Send a message to devices subscribed to the provided topic.
admin.messaging().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 enviará mensagens para dispositivos que estão inscritos em TopicA e em 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 e TopicB
  • TopicA e TopicC

É possível 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.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
var message = {
  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.
admin.messaging().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(new Notification(
        "$GOOG up 1.43% on the day",
        "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day."))
    .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