Ir a la consola

Envía mensajes a varios dispositivos en iOS

Firebase Cloud Messaging ofrece dos maneras de enviar un mensaje a varios dispositivos:

  • Los mensajes por tema, que permiten enviar un mensaje a varios dispositivos que hayan aceptado un tema específico.
  • Los mensajes por grupos de dispositivos, que te permiten enviar un mensaje a varias instancias de una app que se ejecute en varios dispositivos de un grupo.

Este instructivo se enfoca en el envío de mensajes por tema desde tu servidor de apps mediante los protocolos HTTP o XMPP para FCM, así como en la recepción y administración de ellos en una app de iOS. En esta página, se indican todos los pasos necesarios para lograrlo, desde la configuración hasta la verificación, por lo que es posible que ya hayas realizado algunos de ellos si configuraste una app cliente de iOS para FCM o si ya enviaste tu primer mensaje.

Agrega Firebase a tu proyecto de iOS

Es posible que hayas completado tareas que aparecen en esta sección si ya habilitaste otras funciones de Firebase para tu app. En el caso de FCM, deberás subir tu clave de autenticación de APNS y registrarte para habilitar las notificaciones remotas.

Requisitos previos

  • Instala Xcode 10.1 o una versión más reciente.

  • Instala CocoaPods 1.4.0 o una versión más reciente.

  • Abre tu proyecto en Xcode.

    • Tu proyecto debe orientarse a iOS 8 o una versión más reciente.

    • Los proyectos Swift deben usar la versión 3.0 o una más reciente.

  • Configura un dispositivo iOS físico o un simulador para ejecutar la app.

    • Para Cloud Messaging, necesitarás los siguientes elementos:

      • Un dispositivo iOS físico
      • Una clave de autenticación de notificaciones push de Apple para tu cuenta de desarrollador de Apple
      • En Xcode, habilita las notificaciones push en App > Capabilities
    • En todos los demás productos de Firebase, puedes usar un dispositivo iOS físico o un simulador.

  • Accede a Firebase con tu Cuenta de Google.

Si aún no tienes un proyecto de Xcode, puedes descargar uno de nuestros ejemplos de inicio rápido si solo quieres probar un producto de Firebase.

Crea un proyecto de Firebase

A fin de poder agregar Firebase a tu app para iOS, debes crear un proyecto de Firebase y conectarlo a la app. Consulta Información sobre los proyectos de Firebase para obtener detalles acerca del tema.

Registra tu app en Firebase

Cuando tengas un proyecto de Firebase, podrás agregarle tu app para iOS.

Visita Información sobre los proyectos de Firebase a fin de obtener detalles sobre las recomendaciones y consideraciones para agregar apps a un proyecto de Firebase, incluido cómo manejar diversas variantes de compilación.

  1. En el centro de la página de descripción general del proyecto en Firebase console, haz clic en el ícono de iOS para iniciar el flujo de trabajo de la configuración.

    Si ya agregaste una app a tu proyecto de Firebase, haz clic en Agregar app para que se muestren las opciones de la plataforma.

  2. Ingresa el ID del paquete de la app en el campo ID del paquete de iOS.

    • Abre tu app en Xcode para encontrar el ID del paquete. Luego, accede a la pestaña General en el directorio Runner de nivel superior. El valor del campo Identificador de paquete es el ID del paquete de iOS (por ejemplo, com.yourcompany.yourproject).
  3. Ingresa otra información de la app si el flujo de trabajo de configuración lo solicita (opcional).

  4. Haz clic en Registrar app.

Agrega un archivo de configuración de Firebase

  1. Haz clic en Descargar GoogleService-Info.plist a fin de obtener el archivo de configuración de Firebase para iOS (GoogleService-Info.plist).

  2. Traslada el archivo de configuración al directorio raíz de tu proyecto de Xcode. Si se te solicita, selecciona la opción para agregar el archivo de configuración a todos los destinos.

Si tienes varios ID de paquete en tu proyecto, debes asociar cada uno con una app registrada en Firebase console a fin de que cada app tenga su propio archivo GoogleService-Info.plist.

Agrega los SDK de Firebase a tu app

Te recomendamos que uses CocoaPods para instalar las bibliotecas de Firebase. Si prefieres no usarlo, puedes integrar los marcos de trabajo del SDK directamente.

Ten en cuenta que, si usas una de las muestras de inicio rápido, estas ya contienen el proyecto de Xcode y el Podfile (con pods), pero, de todas formas, debes agregar tu archivo de configuración de Firebase y, luego, instalar los pods.

Puedes agregar cualquiera de los productos de Firebase admitidos a tu app para iOS.

  1. Crea un Podfile si aún no tienes uno. Para ello, ejecuta los siguientes comandos:

    cd your-project-directory
    pod init
  2. En tu Podfile, agrega los pods que deseas usar en tu app.

    pod 'Firebase/Core'
    pod 'Firebase/Messaging'

    Esto agregará las bibliotecas que son necesarias para comenzar a usar Firebase en tu app de iOS.

  3. Instala los pods y abre el archivo .xcworkspace para ver el proyecto en Xcode. Puedes hacerlo con los siguientes comandos:

    pod install
    open your-project.xcworkspace

Sube tu clave de autenticación de APNS

Sube la clave de autenticación del APNS a Firebase. Si aún no tienes una, consulta Configura APNS con FCM.

  1. Dentro del proyecto en Firebase console, selecciona el ícono de ajustes, elige Configuración del proyecto y, luego, la pestaña Cloud Messaging.

  2. En Clave de autenticación de APNS, en Configuración de app para iOS, haz clic en el botón Subir.

  3. Busca la ubicación en la que guardaste la clave, selecciónala y haz clic en Abrir. Agrega el ID de clave correspondiente (disponible en Certificados, identificadores y perfiles en el Centro de miembros desarrolladores de Apple) y haz clic en Subir.

Inicializa Firebase en tu app

Debes agregar el código de inicialización de Firebase a tu aplicación. Importa el módulo de Firebase y configura una instancia compartida de la siguiente manera:

  1. Importa el módulo de Firebase en tu UIApplicationDelegate:

    Swift

    import Firebase

    Objective-C

    @import Firebase;
  2. Configura una instancia compartida de FirebaseApp, generalmente en el método application:didFinishLaunchingWithOptions: de tu app:

    Swift

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

    Objective-C

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

Regístrate para habilitar las notificaciones remotas

Durante el inicio o en el punto que desees del flujo de tu aplicación, registra tu app para habilitar las notificaciones remotas. Llama a registerForRemoteNotifications de la siguiente manera:

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];

Suscribe la app cliente a un tema

Las apps cliente se pueden suscribir a cualquier tema existente o pueden crear un tema nuevo. Cuando una app cliente se suscribe a un nombre de tema nuevo (uno que no existe aún para tu proyecto de Firebase), se crea un tema nuevo con ese nombre en FCM y cualquier cliente se puede suscribir a él posteriormente.

Para suscribirte a un tema, llama al método de suscripción desde el subproceso principal de la aplicación (FCM no tiene seguridad en los subprocesos). Si la solicitud de suscripción falla en el inicio, FCM vuelve a intentarlo automáticamente. Cuando la suscripción no se puede completar, esta genera un error que puedes capturar en un controlador de finalización, como se muestra a continuación:

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

Esta llamada realiza una solicitud asíncrona al backend de FCM y suscribe al cliente al tema determinado. Antes de llamar a subscribeToTopic:topic, asegúrate de que la instancia de app cliente ya haya recibido un token de registro mediante la devolución de llamada didReceiveRegistrationToken.

Cada vez que la app se inicia, FCM se asegura de que todos los temas solicitados estén suscritos. Para anular la suscripción, llama a unsubscribeFromTopic:topic y FCM anulará la suscripción del tema en segundo plano.

Recibe y administra mensajes a temas

FCM entrega mensajes por temas de la misma manera que otros mensajes descendentes.

Implementa AppDelegate application:didReceiveRemoteNotification: como se muestra a continuación:

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

Crea solicitudes de envío

Puedes enviar mensajes al tema después de haber creado uno, ya sea mediante la suscripción de instancias de la app cliente al tema del cliente o a través de la API del servidor. Especifica el nombre que quieres darle al tema en la lógica de envío del backend, como se muestra a continuación:

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 de 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 un mensaje a una combinación de temas, debes especificar una condición, es decir, una expresión booleana en la que se especifican los temas de destino. Por ejemplo, la siguiente condición enviará mensajes a los dispositivos suscritos a TopicA y a TopicB o TopicC:

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

En primer lugar, FCM evalúa las condiciones en paréntesis y, luego, evalúa la expresión de izquierda a derecha. En la expresión anterior, un usuario suscrito a uno solo de los temas no recibirá el mensaje. Asimismo, un usuario que no está suscrito a TopicA no recibirá el mensaje. Las siguientes combinaciones sí lo reciben:

  • TopicA y TopicB
  • TopicA y TopicC

Puedes incluir hasta cinco temas en tu expresión condicional.

Para enviar mensajes a una condición, haz lo siguiente:

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 de 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óximos pasos