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 iOS. Nesta página, descrevemos todas as etapas, 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 do 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, você precisará fazer upload da chave de autenticação de APNs e se registrar para receber notificações remotas.

Pré-requisitos

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

  • Xcode 9.4.1 ou posterior
  • 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 seu 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 app.

Para criar um projeto do Firebase:

  1. Acesse o Console do Firebase.

  2. Clique em Adicionar projeto e selecione ou insira o Nome do projeto.

    • Se você tiver um projeto do Google associado ao seu aplicativo, selecione o projeto no menu suspenso Nome do projeto.
    • Se você não tiver um projeto do Google, insira o novo Nome do projeto.
  3. (Opcional) Edite o código do projeto.

    O Firebase atribui automaticamente um código exclusivo ao seu projeto. Ele é exibido em serviços do Firebase visíveis publicamente, por exemplo:

    • URL padrão do Realtime Database: your-project-id.firebaseio.com
    • Nome padrão do intervalo do Cloud Storage: your-project-id.appspot.com
    • Subdomínio padrão do Hosting: your-project-id.firebaseapp.com
  4. Siga as demais etapas de configuração no Console do Firebase e clique em Criar projeto, ou Adicionar Firebase, se estiver usando um projeto atual do Google.

O Firebase provisiona recursos automaticamente para seu projeto. O processo normalmente leva alguns minutos. Quando o processo for concluído, você será direcionado para a página de visão geral do seu projeto no Console do Firebase.

Agora que você tem um projeto, adicione seu aplicativo 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 solicitar 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 adicionar o arquivo de configuração a todos os destinos.

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

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/Core'
    pod 'Firebase/Messaging'
    

    Esse procedimento adicionará as bibliotecas de pré-requisitos necessárias para colocar o Firebase em funcionamento no seu aplicativo 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 em Certificates, Identifiers & Profiles no Apple Developer Member Center, 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 geralmente está no método application:didFinishLaunchingWithOptions: do app:

    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

O envio de mensagens a um tópico do Firebase Cloud Messaging é muito semelhante ao envio a um dispositivo individual ou a um grupo de usuários. O servidor do app define a chave to com um valor como /topics/yourTopic. Os desenvolvedores podem escolher um nome de tópico que corresponda à expressão regular: "/topics/[a-zA-Z0-9-_.~%]+".

Para enviar a combinações de vários tópicos, a chave condition (em vez da chave to) precisa ser definida como uma condição booleana que especifica os tópicos de destino no servidor de apps. Por exemplo, para enviar mensagens para dispositivos que se inscreveram no TopicA e também no TopicB ou TopicC:

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

Primeiramente, o FCM avalia todas as condições entre parênteses. Em seguida, ele avalia a expressão 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 no TopicA também não receberá a mensagem. As seguintes combinações receberão a mensagem:

  • TopicA e TopicB
  • TopicA e TopicC

Você pode incluir até cinco tópicos em sua expressão condicional, e parênteses são aceitos. Operadores aceitos: &&, ||, !. Observe o uso para !:

!('TopicA' in topics)

Com essa expressão, todas as instâncias do app que não estão inscritas no TopicA recebem a mensagem, inclusive as que não estão inscritas em nenhum tópico.

Para ver mais detalhes sobre as chaves do servidor do app, consulte as informações de referência do protocolo do servidor de conexão selecionado, HTTP ou XMPP. Veja nesta página exemplos de como enviar mensagens para tópicos nesses protocolos.

Solicitação HTTP POST de tópico

Enviar para um único tópico:

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to" : /topics/foo-bar",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}

Enviar para dispositivos inscritos nos tópicos "dogs" ou "cats":

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "condition": "'dogs' in topics || 'cats' in topics",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}

Resposta HTTP de tópico

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

Mensagem XMPP de tópico

Enviar para um único tópico:

<message id="">
  <gcm xmlns="google:mobile:data">

{
  "to" : /topics/foo-bar",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}
  </gcm>
</message>

Enviar para dispositivos inscritos nos tópicos "dogs" ou "cats":

<message id="">
  <gcm xmlns="google:mobile:data">

{
  "condition": "'dogs' in topics || 'cats' in topics",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}
  </gcm>
</message>

Resposta XMPP de tópico

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

Aguarde até 30 segundos para que o servidor de conexão do FCM retorne uma resposta de êxito ou falha para as solicitações de envio de tópico. Defina corretamente o valor de tempo limite do servidor de apps na solicitação.

Para ver a lista completa de opções de mensagens, consulte as informações de referência do protocolo do servidor de conexão selecionado (HTTP ou XMPP).

Próximas etapas

Enviar comentários sobre…

Precisa de ajuda? Acesse nossa página de suporte.