Implementar Expo Push Notifications para notificaciones PUSH en React Native (Android/iOS)

Tiempo de lectura: 3 minutos

Hoy vamos a implementar notificaciones PUSH en Android/iOS para React Native utilizando la libreria de Expo Notifications.

Pexels - Desierto

Lo primero que haremos es instalar las librerías necesarias:

npx expo install expo-notifications expo-device expo-constants

Una vez instaladas utilizaremos este código que ademas genera dos tipos de tokens:

import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';
import { Platform } from 'react-native';
import Constants from 'expo-constants';

export enum PushTokenType {
    Expo = 'expo',
    Fcm = 'fcm',
}

/**
 * Pide permisos de notificaciones al usuario.
 * @param tokenType PushTokenType.Expo -> ExponentPushToken[...] (usa Expo Push API)
 *                  PushTokenType.Fcm  -> token nativo FCM/APNs (compatible con tu backend actual)
 */
export async function requestUserNotificationsPermission(
    tokenType: PushTokenType = PushTokenType.Expo
): Promise<string> {
    try {
        if (!Device.isDevice) {
            console.log('Las notificaciones push requieren un dispositivo físico');
            return "-1";
        }

        const { status: existingStatus } = await Notifications.getPermissionsAsync();
        let finalStatus = existingStatus;

        if (existingStatus !== 'granted') {
            const { status } = await Notifications.requestPermissionsAsync();
            finalStatus = status;
        }

        const enabled = finalStatus === 'granted';

        console.log('User granted permission: ', enabled);

        if (Platform.OS === 'android') {
            await Notifications.setNotificationChannelAsync('default', {
                name: 'default',
                importance: Notifications.AndroidImportance.MAX,
            });
        }

        if (!enabled) {
            return "-1";
        }

        switch (tokenType) {
            case PushTokenType.Expo:
                return await GetExpoPushToken();
            case PushTokenType.Fcm:
                return await GetFCMToken();
            default:
                return "-1";
        }

    } catch (error) {
        console.log('Error in requestUserNotificationsPermission: ', error);
        return "-1";
    }
}

/**
 * Token formato ExponentPushToken[xxxxxxxxxxxx]
 * Para usar con la Expo Push API (https://exp.host/--/api/v2/push/send)
 */
export async function GetExpoPushToken(): Promise<string> {
    try {
        const projectId =
            Constants?.expoConfig?.extra?.eas?.projectId ??
            Constants?.easConfig?.projectId;

        if (!projectId) {
            throw new Error('No se encontró el projectId de EAS (revisa app.json/app.config)');
        }

        const tokenResponse = await Notifications.getExpoPushTokenAsync({ projectId });
        return tokenResponse.data;
    } catch (error) {
        console.log('Error getting Expo push token: ', error);
        return "-1";
    }
}

/**
 * Token nativo (FCM en Android, APNs en iOS)
 * Mismo formato que ya tienes guardado, para seguir usando tu backend/FCM directo
 */
export async function GetFCMToken(): Promise<string> {
    try {
        const tokenResponse = await Notifications.getDevicePushTokenAsync();
        return tokenResponse.data;
    } catch (error) {
        console.log('Error getting device push token: ', error);
        return "-1";
    }
}

Modos de token:

getExpoPushTokenAsync() → token formato ExponentPushToken[...], pensado para usar el servicio de push de Expo. Los tokens FCM viejos no sirven aquí tendrías que volver a pedir permiso/registrar cada dispositivo para obtener tokens nuevos en este formato. No hay forma de «convertir» un FCM token a Expo token sin que el dispositivo vuelva a registrarse.

getDevicePushTokenAsync() devuelve el token nativo (FCM en Android, APNs en iOS).

Y forma de uso:

                //Notificaciones Token:
                try {
                    const tokenNotificaciones = await requestUserNotificationsPermission(PushTokenType.Fcm);

                    if (tokenNotificaciones && tokenNotificaciones !== "-1") {
                      ...

                      ENVIAR A SERVIDOR POR EJEMPLO...


                    } else {
                        console.log("No se pudo obtener el token de notificaciones");
                    }

                } catch (error) {
                    console.log("Error al obtener token de notificaciones:", error);
                    // Aquí puedes decidir continuar igual o mostrar un aviso
                }

Personalizar icono y sonidos:

{
  "expo": {
    "plugins": [
      [
        "expo-notifications",
        {
          "icon": "./local/assets/notification_icon.png",
          "color": "#ffffff",
          "defaultChannel": "default",
          "sounds": [
            "./local/assets/notification_sound.wav",
            "./local/assets/notification_sound_other.wav"
          ],
          "enableBackgroundRemoteNotifications": false
        }
      ]
    ]
  }
}

Nota para el icono: debe ser en tamaño 96×96 y totalmente blanco.

Para iniciar este plugin es necesario que tengas conexion con eas:

npx eas init

Inicia sesión en tu cuenta o crea una nueva y conectala al proyecto.

Deja un comentario