Implementar funcionalidades clave con Expo APIs

Lectura
20 min~5 min lectura

Concepto clave

Las Expo APIs son interfaces preconstruidas que exponen funcionalidades nativas del dispositivo a través de JavaScript, permitiendo acceder a hardware y servicios del sistema operativo sin necesidad de código nativo. Piensa en ellas como un conjunto de herramientas estandarizadas que te permiten interactuar con la cámara, notificaciones push, almacenamiento local y otros recursos del dispositivo de forma consistente entre iOS y Android.

En el desarrollo de aplicaciones de productividad, estas APIs son fundamentales para crear experiencias ricas y funcionales. Por ejemplo, una aplicación de tareas podría usar Expo Notifications para recordatorios, Expo FileSystem para guardar documentos localmente, y Expo SQLite para almacenamiento estructurado. La analogía sería como tener un kit de herramientas de taller completo: cada API es una herramienta específica (martillo, destornillador, llave) que realiza una función precisa sin que tengas que fabricarla desde cero.

Cómo funciona en la práctica

Para implementar funcionalidades clave en nuestra aplicación de productividad, seguimos un flujo estructurado. Primero, identificamos qué APIs de Expo necesitamos basándonos en los requisitos de la funcionalidad. Segundo, instalamos los paquetes necesarios usando npx expo install. Tercero, configuramos los permisos requeridos en el archivo app.json. Cuarto, implementamos la lógica de la API en nuestro código, manejando adecuadamente los estados de carga y error.

Veamos un ejemplo concreto: implementar notificaciones locales para recordatorios de tareas. El proceso paso a paso sería: 1) Instalar expo-notifications, 2) Configurar permisos en app.json, 3) Solicitar permisos al usuario al iniciar la app, 4) Programar notificaciones cuando se crea una tarea con fecha límite, 5) Manejar la interacción del usuario con las notificaciones.

Código en acción

Implementemos un sistema de notificaciones para nuestra app de productividad. Primero, el código básico para solicitar permisos y programar una notificación:

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

// Configurar el manejo de notificaciones
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: true,
  }),
});

// Función para solicitar permisos
async function solicitarPermisosNotificaciones() {
  if (Device.isDevice) {
    const { status: statusExistente } = await Notifications.getPermissionsAsync();
    let statusFinal = statusExistente;
    
    if (statusExistente !== 'granted') {
      const { status } = await Notifications.requestPermissionsAsync();
      statusFinal = status;
    }
    
    if (statusFinal !== 'granted') {
      alert('Se necesitan permisos para enviar notificaciones');
      return false;
    }
    
    // En Android, necesitamos configurar el canal de notificaciones
    if (Platform.OS === 'android') {
      await Notifications.setNotificationChannelAsync('recordatorios', {
        name: 'Recordatorios de tareas',
        importance: Notifications.AndroidImportance.HIGH,
        vibrationPattern: [0, 250, 250, 250],
        lightColor: '#FF231F7C',
      });
    }
    
    return true;
  } else {
    alert('Debes usar un dispositivo físico para notificaciones');
    return false;
  }
}

// Función para programar una notificación
async function programarNotificacion(titulo, cuerpo, fecha) {
  const permisosOtorgados = await solicitarPermisosNotificaciones();
  
  if (!permisosOtorgados) {
    return null;
  }
  
  const identificador = await Notifications.scheduleNotificationAsync({
    content: {
      title: titulo,
      body: cuerpo,
      data: { tipo: 'recordatorio_tarea' },
      sound: 'default',
    },
    trigger: {
      date: fecha, // Fecha y hora específica
    },
  });
  
  return identificador;
}

Ahora, mejoremos este código agregando manejo de errores y cancelación de notificaciones:

// Versión mejorada con manejo de errores
async function programarNotificacionMejorada(titulo, cuerpo, fecha) {
  try {
    const permisosOtorgados = await solicitarPermisosNotificaciones();
    
    if (!permisosOtorgados) {
      throw new Error('Permisos de notificación no otorgados');
    }
    
    // Validar que la fecha sea futura
    if (fecha <= new Date()) {
      throw new Error('La fecha de la notificación debe ser futura');
    }
    
    const identificador = await Notifications.scheduleNotificationAsync({
      content: {
        title: titulo || 'Recordatorio',
        body: cuerpo || 'Tienes una tarea pendiente',
        data: { 
          tipo: 'recordatorio_tarea',
          timestamp: Date.now()
        },
        sound: 'default',
        priority: Notifications.AndroidNotificationPriority.HIGH,
      },
      trigger: {
        date: fecha,
      },
    });
    
    console.log(`Notificación programada con ID: ${identificador}`);
    return identificador;
    
  } catch (error) {
    console.error('Error al programar notificación:', error.message);
    // Podríamos registrar este error en un servicio de analytics
    return null;
  }
}

// Función para cancelar una notificación
async function cancelarNotificacion(identificador) {
  if (!identificador) return;
  
  try {
    await Notifications.cancelScheduledNotificationAsync(identificador);
    console.log(`Notificación ${identificador} cancelada`);
  } catch (error) {
    console.error('Error al cancelar notificación:', error);
  }
}

Errores comunes

  • No verificar permisos antes de usar la API: Intentar usar Notifications sin haber solicitado permisos primero causará errores silenciosos. Siempre verifica el estado de permisos y solicítalos si es necesario.
  • Olvidar configurar canales en Android: En Android 8+, las notificaciones requieren canales configurados. Sin esto, las notificaciones no se mostrarán correctamente.
  • No manejar el estado "no es un dispositivo": En simuladores o emuladores, algunas APIs no funcionan. Siempre verifica con Device.isDevice antes de usar APIs de hardware.
  • Programar notificaciones con fechas pasadas: Esto puede causar comportamientos inesperados. Siempre valida que la fecha del trigger sea futura.
  • No limpiar notificaciones canceladas: Si permites a los usuarios eliminar tareas, asegúrate de cancelar también sus notificaciones programadas para evitar notificaciones huérfanas.

Checklist de dominio

  1. Puedo explicar la diferencia entre Expo APIs y APIs nativas de React Native
  2. He implementado al menos 3 APIs diferentes de Expo en un proyecto real
  3. Sé cómo manejar permisos de usuario para diferentes APIs (notificaciones, cámara, ubicación)
  4. Puedo debuggear problemas comunes de APIs de Expo usando logs y la documentación oficial
  5. He implementado manejo de errores robusto para fallos de APIs
  6. Sé cómo optimizar el uso de APIs para mejor rendimiento (lazy loading, cleanup)
  7. Puedo integrar múltiples APIs de Expo que interactúen entre sí en una funcionalidad compleja

Implementar sistema completo de recordatorios con Expo APIs

En este ejercicio, implementarás un sistema completo de recordatorios para la aplicación de productividad usando múltiples APIs de Expo. Sigue estos pasos:

  1. Configuración inicial: Crea un nuevo componente RecordatoriosManager.js en tu proyecto. Instala las dependencias necesarias: expo-notifications, expo-device, y expo-calendar si quieres integración con calendario nativo.
  2. Implementa el núcleo: Crea una función programarRecordatorio que acepte título, descripción, fecha y repetición (diaria, semanal, ninguna). Usa expo-notifications para programar la notificación. Para repeticiones, investiga el trigger calendar en la documentación.
  3. Agrega persistencia: Usa expo-sqlite para guardar los recordatorios programados en una base de datos local. Crea una tabla con campos: id, título, descripción, fecha_programada, repetir, notificacion_id.
  4. Implementa UI: Crea una pantalla donde los usuarios puedan ver todos sus recordatorios programados, con opción de editar o eliminar. Al eliminar un recordatorio, también cancela la notificación correspondiente.
  5. Agrega características avanzadas: Implementa una función que verifique al iniciar la app si hay recordatorios pasados que no se ejecutaron (por ejemplo, si la app estaba cerrada) y los reprograma para el próximo intervalo válido.
  6. Testing: Prueba tu implementación en dispositivo físico, verificando que las notificaciones se muestran correctamente y que la persistencia funciona después de reiniciar la app.
Pistas
  • Usa async/await consistentemente para manejar las operaciones asíncronas de las APIs
  • Para las repeticiones, considera usar cron expressions o la API de calendar triggers de expo-notifications
  • No olvides limpiar los listeners de notificaciones en el cleanup de useEffect

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.