tutoriales.com

Integrando Notificaciones Push en React Native con Firebase Cloud Messaging (FCM)

Este tutorial detalla el proceso de integración de notificaciones push en aplicaciones React Native utilizando Firebase Cloud Messaging (FCM). Cubriremos la configuración de Firebase, la instalación de las dependencias necesarias y la implementación del código para enviar y recibir notificaciones en Android e iOS. Al finalizar, tendrás una comprensión clara de cómo potenciar la interacción con tus usuarios a través de alertas en tiempo real.

Intermedio18 min de lectura17 views
Reportar error
Integrando Notificaciones Push en React Native con Firebase Cloud Messaging (FCM)

Las notificaciones push son una herramienta esencial para cualquier aplicación móvil moderna. Permiten a los desarrolladores enviar mensajes a los usuarios en cualquier momento, incluso cuando la aplicación no está abierta, mejorando la retención y el engagement. En este tutorial, exploraremos cómo implementar notificaciones push en tu aplicación React Native utilizando Firebase Cloud Messaging (FCM).

FCM es una solución robusta y gratuita de Google que permite enviar notificaciones a Android, iOS y aplicaciones web. Es escalable, fiable y fácil de integrar.

🚀 ¿Por qué Firebase Cloud Messaging (FCM)?

FCM ofrece una serie de ventajas que lo convierten en la opción preferida para la mayoría de los desarrolladores:

  • Gratuito y escalable: No hay costos asociados al envío de notificaciones y puede manejar millones de dispositivos.
  • Multiplataforma: Soporte nativo para Android, iOS y la web.
  • Flexibilidad: Permite enviar notificaciones a dispositivos individuales, grupos de dispositivos o temas.
  • Mensajes de datos: Además de las notificaciones visibles, permite enviar datos personalizados a tu aplicación para un manejo más avanzado.
  • Integración con Firebase: Se integra perfectamente con otros servicios de Firebase como Analytics, Authentication, y Crashlytics.
📌 Nota: Este tutorial asume que ya tienes un proyecto de React Native configurado y funcionando. Si no es así, puedes crear uno con `npx react-native init MiAppNotificaciones`.

🛠️ Requisitos Previos

Antes de empezar, asegúrate de tener lo siguiente:

  • Node.js y npm/yarn instalados.
  • React Native CLI o Expo CLI (si usas Expo, considera la versión "bare workflow" para este tutorial).
  • Una cuenta de Google.
  • Un dispositivo Android o emulador, y un dispositivo iOS o simulador (con Xcode configurado).
  • APN Key (iOS): Para iOS, necesitarás generar un archivo AuthKey_XXXXXX.p8 de Apple Developer. Explicaremos esto en detalle más adelante.

1. Configuración del Proyecto Firebase ⚙️

El primer paso es crear y configurar un proyecto de Firebase para tu aplicación.

1.1 Crear un Proyecto Firebase

  1. Ve a la Consola de Firebase.
  2. Haz clic en "Añadir proyecto".
  3. Introduce un nombre para tu proyecto (por ejemplo, MiAppNotificacionesRN).
  4. Sigue los pasos y, si lo deseas, habilita Google Analytics para este proyecto. Haz clic en "Crear proyecto".

1.2 Añadir tu Aplicación Android a Firebase

  1. Una vez creado el proyecto, en la vista general, haz clic en el icono de Android (el robot verde).

  2. Introduce el "Nombre del paquete de Android" (Package name). Este debe coincidir con el applicationId en tu archivo android/app/build.gradle (por ejemplo, com.miappnotificaciones).

  3. Opcional: Introduce un nombre de aplicación y SHA-1 (puedes añadirlo más tarde si es necesario para autenticación). Haz clic en "Registrar aplicación".

  4. Descarga el archivo google-services.json. Este archivo contiene la configuración de Firebase para tu aplicación Android. Colócalo en el directorio android/app de tu proyecto React Native.

  5. Sigue las instrucciones para añadir el SDK de Firebase a tu proyecto Android. Tendrás que modificar los archivos android/build.gradle (proyecto) y android/app/build.gradle (módulo).

    android/build.gradle (proyecto):

buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
// ... otras dependencias
classpath 'com.google.gms:google-services:4.4.1' // Asegúrate de la última versión
}
}

allprojects {
repositories {
mavenCentral()
google()
// ... otros repositorios
}
}
**`android/app/build.gradle` (módulo):**
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services' // Añade esta línea al final

android {
// ...
}

dependencies {
// ... otras dependencias
implementation platform('com.google.firebase:firebase-bom:32.7.4') // Asegúrate de la última versión
implementation 'com.google.firebase:firebase-analytics'
// Para FCM, no necesitas añadir 'firebase-messaging' directamente aquí si usas @react-native-firebase/app
}
  1. Sincroniza tu proyecto Gradle. Puedes hacer esto ejecutando npx react-native run-android o abriendo el proyecto en Android Studio y haciendo clic en "Sync Project with Gradle Files".

1.3 Añadir tu Aplicación iOS a Firebase

  1. En la vista general de tu proyecto Firebase, haz clic en el icono de iOS (la manzana).

  2. Introduce el "ID de paquete de iOS" (Bundle ID). Este debe coincidir con el Bundle Identifier en Xcode (por ejemplo, org.reactjs.native.example.MiAppNotificaciones).

  3. Opcional: Introduce un nombre de aplicación y App Store ID. Haz clic en "Registrar aplicación".

  4. Descarga el archivo GoogleService-Info.plist. Colócalo en el directorio ios/MiAppNotificaciones de tu proyecto (donde MiAppNotificaciones es el nombre de tu proyecto iOS) y arrástralo a tu proyecto en Xcode (asegúrate de que "Copy items if needed" esté marcado y que se añada a tu target).

  5. Sigue las instrucciones para añadir el SDK de Firebase a tu proyecto iOS. Tendrás que modificar tu AppDelegate.mm (o AppDelegate.m si es Objective-C).

    **ios/MiAppNotificaciones/AppDelegate.mm (o AppDelegate.m):

#import "AppDelegate.h"
#import <Firebase.h>
#import <React/RCTBundleURLProvider.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ...
[FIRApp configure]; // Añade esta línea

return YES;
}

// ... otras funciones

@end
  1. Habilitar Push Notifications en Xcode:
    • Abre tu proyecto iOS en Xcode (ios/MiAppNotificaciones.xcworkspace).
    • Selecciona tu proyecto en el navegador de proyectos.
    • Ve a la pestaña "Signing & Capabilities".
    • Haz clic en + Capability y añade "Push Notifications" y "Background Modes".
    • Dentro de "Background Modes", marca "Remote notifications".
1. Abrir Xcode 2. Seleccionar Proyecto 3. Pestaña 'Signing & Capabilities' 4. + Capability 5. Seleccionar 'Push Notifications' 6. Seleccionar 'Background Modes' 7. Marcar 'Remote notifications'

2. Instalación de Dependencias de React Native Firebase ✨

React Native Firebase es la biblioteca oficial que nos permite interactuar con los servicios de Firebase en nuestras aplicaciones React Native. Necesitaremos instalar @react-native-firebase/app y @react-native-firebase/messaging.

npm install @react-native-firebase/app @react-native-firebase/messaging
# o
yarn add @react-native-firebase/app @react-native-firebase/messaging

Después de instalar los paquetes, es crucial enlazar las dependencias nativas (aunque con React Native 0.60+ autolinking debería encargarse de esto).

npx pod-install ios
🔥 Importante: Para iOS, necesitarás una clave de autenticación (`.p8`) para enviar notificaciones push. Esto se configura en Firebase, en `Project settings > Cloud Messaging > iOS app configuration`. Sube el archivo `.p8` que descargaste de tu cuenta de desarrollador de Apple.

3. Implementación del Código React Native 💻

Ahora que todo está configurado, podemos empezar a escribir el código en nuestra aplicación React Native para manejar las notificaciones.

3.1 Solicitar Permisos y Obtener el Token FCM

Las notificaciones push requieren que el usuario otorgue permiso. También necesitamos obtener el token de registro de FCM para el dispositivo, que usaremos para enviar notificaciones a ese dispositivo específico.

Modifica tu archivo App.js o el componente principal donde desees manejar la lógica de notificaciones.

import React, { useEffect } from 'react';
import { Alert, StyleSheet, Text, View, Platform } from 'react-native';
import messaging from '@react-native-firebase/messaging';

async function requestUserPermission() {
  const authStatus = await messaging().requestPermission();
  const enabled = 
    authStatus === messaging.AuthorizationStatus.AUTHORIZED |
    authStatus === messaging.AuthorizationStatus.PROVISIONAL;

  if (enabled) {
    console.log('Authorization status:', authStatus);
    getFCMToken();
  }
}

async function getFCMToken() {
  try {
    const token = await messaging().getToken();
    console.log('FCM Token:', token);
    // Aquí podrías enviar el token a tu servidor backend
  } catch (error) {
    console.error('Error al obtener el token FCM:', error);
  }
}

function App() {
  useEffect(() => {
    requestUserPermission();

    // Manejar notificaciones en primer plano (Foreground)
    const unsubscribe = messaging().onMessage(async remoteMessage => {
      Alert.alert(
        'Nueva notificación (Foreground)',
        JSON.stringify(remoteMessage.notification)
      );
      console.log('Mensaje recibido en primer plano:', remoteMessage);
    });

    // Manejar clics en notificaciones cuando la app está en segundo plano (Background) o cerrada (Quit)
    messaging().onNotificationOpenedApp(remoteMessage => {
      console.log(
        'La notificación causó que la aplicación se abriera desde el estado de segundo plano:',
        remoteMessage.notification,
      );
      Alert.alert(
        'App abierta por notificación',
        `Título: ${remoteMessage.notification.title}\nCuerpo: ${remoteMessage.notification.body}`
      );
    });

    // Comprobar si la aplicación se inició a partir de una notificación que se tocó cuando la aplicación se cerró por completo
    messaging()
      .getInitialNotification()
      .then(remoteMessage => {
        if (remoteMessage) {
          console.log(
            'La notificación causó que la aplicación se abriera desde el estado de ' +
              'cerrada:',
            remoteMessage.notification,
          );
          Alert.alert(
            'App iniciada por notificación',
            `Título: ${remoteMessage.notification.title}\nCuerpo: ${remoteMessage.notification.body}`
          );
        }
      });

    return unsubscribe; // Limpiar el listener al desmontar el componente
  }, []);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Notificaciones Push con FCM</Text>
      <Text>Abre la consola de Firebase para enviar un mensaje de prueba.</Text>
      <View style={styles.statusIndicator}>
        <Text style={styles.statusText}>Estado de la notificación:</Text>
        <span class="badge green">Activo</span>
      </View>
      <Text style={styles.infoText}>Asegúrate de conceder permisos de notificación a la aplicación.</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
    backgroundColor: '#f0f4f7',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    color: '#333',
  },
  statusIndicator: {
    flexDirection: 'row',
    alignItems: 'center',
    marginTop: 20,
    padding: 10,
    backgroundColor: '#e6ffe6',
    borderRadius: 8,
    borderWidth: 1,
    borderColor: '#a3e9a3',
  },
  statusText: {
    marginRight: 10,
    fontSize: 16,
    color: '#333',
  },
  infoText: {
    marginTop: 20,
    textAlign: 'center',
    color: '#666',
    fontSize: 14,
  }
});

export default App;
💡 Consejo: El token FCM es único para cada instalación de la aplicación en un dispositivo específico. Si quieres enviar notificaciones a usuarios específicos, deberías almacenar este token en tu base de datos de backend y asociarlo con la cuenta de usuario.

3.2 Manejo de Mensajes en Segundo Plano (Background Messaging)

Para manejar notificaciones cuando la aplicación está en segundo plano o cerrada, necesitamos un headless task en Android y un service extension en iOS.

Android: Headless Task

Crea un nuevo archivo llamado index.js (si no lo tienes) o añade lo siguiente al existente si ya tienes uno para AppRegistry.registerComponent.

import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
import messaging from '@react-native-firebase/messaging';

// Registra un handler para mensajes de segundo plano
messaging().setBackgroundMessageHandler(async remoteMessage => {
  console.log('Mensaje manejado en segundo plano:', remoteMessage);
  // Aquí puedes realizar tareas en segundo plano, como actualizar la UI localmente,
  // mostrar una notificación local personalizada, etc.
});

AppRegistry.registerComponent(appName, () => App);

iOS: Service Extension

Para iOS, necesitas un Service Extension para manejar notificaciones de datos cuando la aplicación está en segundo plano o cerrada. Esto es más complejo y a menudo se usa para modificar el contenido de la notificación antes de que se muestre.

  1. En Xcode: Ve a File > New > Target....
  2. Selecciona Notification Service Extension y haz clic en Next.
  3. Dale un nombre (por ejemplo, ImageNotification) y haz clic en Finish.
  4. Activa el esquema cuando se te pregunte.
  5. Instala las dependencias de React Native Firebase para la extensión:
    • Abre el Podfile de tu proyecto (está en ios/Podfile).
    • Añade esto al final del archivo, fuera del target principal de la aplicación, pero dentro del bloque post_install si ya tienes uno (o crea uno):
target 'ImageNotification' do # Usa el nombre de tu target de extensión
pod 'Firebase/Messaging'
end
*   Luego ejecuta `cd ios && pod install`.

6. Modifica NotificationService.m:

#import "NotificationService.h"
#import <FirebaseMessaging/FIRMessaging.h>

@interface NotificationService ()
@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];

// Modifica la notificación aquí si es necesario (ej: añadir imagen)
// [FIRMessaging extensionHelper].mutableContent(self.bestAttemptContent);

self.contentHandler(self.bestAttemptContent);
}

- (void)serviceExtensionTimeWillExpire {
// Called just before the extension will be terminated by the system.
// Use this as an opportunity to deliver your "best attempt" at modifying the contents of the notification.
self.contentHandler(self.bestAttemptContent);
}

@end

Este paso de iOS es más avanzado y se usa principalmente si necesitas enriquecer las notificaciones (ej. con imágenes) antes de que se muestren. Para notificaciones de texto básicas, el onNotificationOpenedApp y getInitialNotification en App.js suelen ser suficientes para manejar la interacción del usuario.

3.3 Envío de Notificaciones de Prueba desde la Consola de Firebase

Para probar que todo funciona, puedes enviar notificaciones de prueba desde la Consola de Firebase:

  1. Ve a tu proyecto en la Consola de Firebase.
  2. En el menú de la izquierda, selecciona "Cloud Messaging".
  3. Haz clic en "Enviar tu primer mensaje" o "Enviar mensaje".
  4. Introduce un título y un texto para tu mensaje.
  5. En "Destino", selecciona tu aplicación y haz clic en "Enviar a un token de registro". Pega el token FCM que se mostró en la consola de tu aplicación (el que obtuviste con console.log('FCM Token:', token);).
  6. Puedes configurar opciones avanzadas si lo deseas (datos personalizados, sonido, etc.).
  7. Haz clic en "Revisar" y luego en "Publicar".

Observa tu aplicación React Native. Si está en primer plano, deberías ver un Alert. Si está en segundo plano o cerrada y la abres a través de la notificación, deberías ver los logs correspondientes y quizás otro Alert (dependiendo de tu implementación).

¡Casi listo!

💡 Consideraciones Adicionales y Mejores Prácticas

1. Mensajes de Datos vs. Notificaciones

  • Mensajes de Notificación: Son los mensajes visibles para el usuario que FCM maneja automáticamente. Tienen un title y body.
  • Mensajes de Datos: Son payloads JSON que tu aplicación recibe y procesa. No son visibles para el usuario a menos que tu aplicación cree una notificación local. Son útiles para sincronizar datos en segundo plano o para notificaciones altamente personalizadas. Puedes combinar ambos (notification y data payload).

2. Notificaciones Locales

Para mostrar una notificación cuando la aplicación está en primer plano (y recibes un mensaje de datos o una notificación que no quieres que el sistema muestre por defecto), o para crear notificaciones personalizadas, puedes usar una biblioteca como @react-native-community/push-notification-ios (solo iOS) o react-native-push-notification (multiplataforma). Esto te da un control total sobre cómo se muestra la notificación.

// Ejemplo simple con react-native-push-notification (requiere instalación adicional)
// import PushNotification from 'react-native-push-notification';

// messaging().onMessage(async remoteMessage => {
//   console.log('Mensaje recibido en primer plano:', remoteMessage);
//   PushNotification.localNotification({
//     channelId: 'default-channel-id', // Asegúrate de configurar un canal para Android O+
//     title: remoteMessage.notification.title,
//     message: remoteMessage.notification.body,
//     userInfo: remoteMessage.data, // Pasa datos adicionales si los hay
//   });
// });

3. Canales de Notificación (Android O+)

En Android 8.0 (Oreo) y superior, todas las notificaciones deben pertenecer a un canal. Es importante configurar canales de notificación para permitir a los usuarios controlar el tipo de notificaciones que reciben.

// Ejemplo de creación de canal (generalmente al inicio de la app o en el efecto de un componente principal)
import PushNotification from 'react-native-push-notification';

// ... dentro de useEffect
if (Platform.OS === 'android') {
  PushNotification.createChannel(
    {
      channelId: "default-channel-id", // (required) 
      channelName: "Mi Canal por Defecto", // (required)
      channelDescription: "Un canal para notificaciones generales", // (optional)
      playSound: false, // (optional) default: true
      soundName: "default", // (optional) See `soundName` parameter of `localNotification` function
      importance: 4, // (optional) default: 4. Int value of the Android NotificationImportance. Can be: `patch` (0), `low` (1), `min` (2), `default` (3), `high` (4), `max` (5)
      vibrate: true, // (optional) default: true. Creates the default vibration pattern if true.
    },
    (created) => console.log(`createChannel returned '${created}'`)
  );  
}
// ...

4. Personalización del Icono de Notificación (Android)

Por defecto, Android usará el icono de la aplicación. Para un icono de notificación personalizado (monocromático y transparente), debes colocarlo en android/app/src/main/res/mipmap- y referenciarlo en AndroidManifest.xml.

<manifest ...>
  <application ...>
    <meta-data
      android:name="com.google.firebase.messaging.default_notification_icon"
      android:resource="@mipmap/ic_notification" /> <!-- Asegúrate de que este icono exista -->
    <meta-data
      android:name="com.google.firebase.messaging.default_notification_color"
      android:resource="@color/accent_color" /> <!-- Define accent_color en colors.xml -->
    ...
  </application>
</manifest>
Paso 1: Crea un icono monocromático y transparente (por ejemplo, `ic_notification.png`).
Paso 2: Colócalo en las carpetas `mipmap-xxhdpi`, `mipmap-xhdpi`, etc., dentro de `android/app/src/main/res/`.
Paso 3: Edita `AndroidManifest.xml` como se muestra arriba para referenciarlo.

Troubleshooting y Errores Comunes ⚠️

  • google-services.json o GoogleService-Info.plist no encontrados: Asegúrate de que los archivos estén en las ubicaciones correctas y que se hayan añadido correctamente a tu proyecto Xcode.
  • Permisos de Notificación: Verifica que la aplicación tenga permisos para mostrar notificaciones en la configuración del dispositivo.
  • FCM Token no obtenido: Revisa los logs de tu aplicación. Si el token no aparece, puede haber un problema con la configuración de Firebase o las dependencias nativas.
  • Notificaciones no llegan a iOS: Esto es a menudo un problema con la configuración de las APN (Apple Push Notification service). Asegúrate de que tu AuthKey_XXXXXX.p8 esté correctamente cargado en Firebase y que las capacidades de Push Notifications estén habilitadas en Xcode.
  • Notificaciones en Android Oreo+ sin canal: Si no defines un canal, las notificaciones podrían no mostrarse o aparecer con un comportamiento errático.
  • Caché de Gradle/Pods: A veces, limpiar el caché puede resolver problemas. Prueba con cd android && ./gradlew clean (Android) y cd ios && pod deintegrate && pod install (iOS).
¿Qué es un APN Key y por qué es necesario para iOS? Un APN Key (Authentication Key, archivo .p8) es un token de autenticación que generas en tu cuenta de desarrollador de Apple. Este key permite a los servidores de Firebase (o cualquier otro proveedor de notificaciones push) autenticarse de forma segura con los servidores de APN de Apple para enviar notificaciones a tus dispositivos iOS. Es más seguro y flexible que los antiguos certificados .p12 y no caduca, lo que lo hace ideal para la automatización y el mantenimiento a largo plazo.
¿Puedo enviar notificaciones a través de un servidor backend propio? ¡Sí, de hecho, es la forma más común! Una vez que obtienes el token FCM de un dispositivo, lo envías a tu backend y lo almacenas asociado al usuario. Cuando quieras enviar una notificación a ese usuario, tu backend envía una solicitud a la API de FCM (utilizando las credenciales de Firebase que configuraste) con el token de destino y el payload de la notificación. Esto permite una lógica de negocio compleja para el envío de notificaciones.
¿Cómo puedo segmentar usuarios para mis notificaciones? FCM permite varias formas de segmentación:
  • Por Token: Envío a dispositivos individuales usando sus tokens FCM (como hicimos en la prueba).
  • Por Tema: Los usuarios pueden suscribirse a temas (ej. messaging().subscribeToTopic('noticias_deportes')). Luego, tu backend puede enviar notificaciones a todos los suscriptores de un tema.
  • Por Segmento de Audiencia: Integrado con Firebase Analytics, puedes definir audiencias basadas en el comportamiento del usuario y enviarles notificaciones directamente desde la consola de Firebase.
  • Grupos de Dispositivos: Puedes crear grupos lógicos de dispositivos para enviar mensajes a múltiples dispositivos de un solo usuario.

Conclusión ✅

¡Felicidades! Has configurado e integrado exitosamente las notificaciones push de Firebase Cloud Messaging en tu aplicación React Native. Ahora tienes la capacidad de interactuar con tus usuarios de una manera más dinámica y atractiva.

Recuerda que la implementación que hemos cubierto es la base. Las posibilidades son vastas: desde notificaciones locales personalizadas hasta la integración con tu propio backend para enviar mensajes segmentados y basados en eventos. Continúa experimentando y personalizando la experiencia de notificación para tus usuarios.

¡A codificar!

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!