Saltar al contenido

Lección 9 de 20 · Lectura y práctica

Manejar permisos nativos en aplicaciones avanzadas

Concepto claveLos permisos nativos son mecanismos de seguridad que controlan el acceso de una aplicación a recursos sensibles del dispositivo, como la cámara, ubicación, contactos o almacenamiento. En el desarrollo con Expo,.

Del concepto a la práctica

Taller de esta lección

Solicitar un permiso debe estar ligado a una acción comprensible. El flujo correcto distingue permiso concedido, denegado temporalmente y denegado de forma que requiera intervención en ajustes; la aplicación no debe intentar acceder al recurso antes de conocer el estado.

Ejemplo resuelto

Al pulsar “Activar recordatorios”, el estado inicial undetermined abre la solicitud. Si el usuario concede, se programa el recordatorio. Si responde denied, la pantalla explica que la función queda desactivada y ofrece un enlace a ajustes solo cuando el sistema no permite volver a preguntar. Cancelar no se trata como éxito.

Pruébalo

  1. Dibuja los estados undetermined, granted y denied.

  2. Asocia una acción visible a la solicitud.

  3. Simula cada respuesta y registra la siguiente pantalla.

  4. Comprueba que no se programa nada tras un rechazo.

Error frecuente: pedir cámara, ubicación y notificaciones al iniciar la aplicación. Corrígelo solicitando cada permiso justo antes de usar su función.

Comprueba tu resultado

La matriz debe tener tres estados, tres salidas y cero recordatorios programados en los casos de rechazo o cancelación.

Capas de acceso, actualización, copias y respuesta a incidentes alrededor de un sistema.
CursaloMapa de práctica
La seguridad necesita varias capas

El control de acceso, las actualizaciones y las copias de seguridad cubren riesgos distintos. Una alerta necesita un procedimiento de respuesta para contener y recuperar el servicio. Varias capas reducen la exposición, pero ninguna garantiza seguridad absoluta.

Ver la infografía en tamaño completo ↗

Concepto clave

Los permisos nativos son mecanismos de seguridad que controlan el acceso de una aplicación a recursos sensibles del dispositivo, como la cámara, ubicación, contactos o almacenamiento. En el desarrollo con Expo, estos permisos actúan como puertas de acceso que requieren autorización explícita del usuario antes de que tu aplicación pueda utilizar funcionalidades específicas del sistema operativo.

Imagina que estás construyendo una casa inteligente. Los permisos nativos serían como las llaves que necesitas para acceder a diferentes áreas: necesitas una llave específica para entrar al garaje (cámara), otra para el sistema de seguridad (ubicación), y otra para la red doméstica (almacenamiento). Sin estas llaves, aunque tengas la tecnología, no puedes operar esas funcionalidades. En Expo, este sistema de "llaves" está estandarizado a través de APIs como expo-permissions (legacy) y el nuevo sistema modular con expo-camera, expo-location, entre otros.

Cómo funciona en la práctica

El flujo de trabajo para manejar permisos en Expo sigue un patrón consistente: primero verificas el estado actual del permiso, luego solicitas acceso si es necesario, y finalmente manejas la respuesta del usuario. Este proceso es crucial porque los sistemas operativos iOS y Android tienen políticas diferentes sobre cuándo y cómo solicitar permisos.

Paso a paso, el proceso es:

  1. Importar el módulo específico (ej: expo-camera para permisos de cámara)
  2. Verificar el estado actual del permiso usando métodos como getPermissionsAsync()
  3. Si el permiso no está concedido, solicitar acceso con requestPermissionsAsync()
  4. Manejar la respuesta del usuario apropiadamente
  5. Implementar fallbacks para cuando el usuario deniega el permiso

Un aspecto avanzado es el manejo de permisos que requieren justificación en tiempo de ejecución (runtime), especialmente en iOS, donde debes proporcionar strings de descripción en tu Info.plist que expliquen por qué necesitas cada permiso.

Código en acción

Veamos un ejemplo completo de manejo de permisos de cámara usando el enfoque moderno de Expo:

import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, Alert } from 'react-native';
import { Camera } from 'expo-camera';

const CameraScreen = () => {
  const [hasPermission, setHasPermission] = useState(null);
  const [cameraRef, setCameraRef] = useState(null);

  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestCameraPermissionsAsync();
      setHasPermission(status === 'granted');
      
      if (status !== 'granted') {
        Alert.alert(
          'Permiso requerido',
          'Necesitamos acceso a la cámara para tomar fotos.',
          [
            {
              text: 'Configuración',
              onPress: () => Linking.openSettings(),
            },
            { text: 'Cancelar', style: 'cancel' },
          ]
        );
      }
    })();
  }, []);

  const takePicture = async () => {
    if (cameraRef && hasPermission) {
      const photo = await cameraRef.takePictureAsync();
      console.log('Foto tomada:', photo.uri);
    }
  };

  if (hasPermission === null) {
    return Solicitando permiso...;
  }
  
  if (hasPermission === false) {
    return Sin acceso a la cámara;
  }

  return (
    
       setCameraRef(ref)}
      >
        
          
            Tomar foto
          
        
      
    
  );
};

const styles = StyleSheet.create({
  container: { flex: 1 },
  camera: { flex: 1 },
  buttonContainer: {
    flex: 1,
    backgroundColor: 'transparent',
    flexDirection: 'row',
    margin: 20,
  },
  button: {
    flex: 0.1,
    alignSelf: 'flex-end',
    alignItems: 'center',
  },
  text: { fontSize: 18, color: 'white' },
});

export default CameraScreen;

Ahora, veamos cómo refactorizar código legacy que usa expo-permissions al nuevo sistema modular:

ANTES (enfoque legacy):

import * as Permissions from 'expo-permissions';

const requestCameraPermission = async () => {
  const { status } = await Permissions.askAsync(Permissions.CAMERA);
  return status === 'granted';
};

DESPUÉS (enfoque modular):

import { Camera } from 'expo-camera';

const requestCameraPermission = async () => {
  const { status } = await Camera.requestCameraPermissionsAsync();
  return status === 'granted';
};

Errores comunes

  • Solicitar permisos muy temprano: Pedir permisos al iniciar la aplicación sin contexto puede reducir las tasas de aceptación. Solución: Solicita permisos en el momento en que el usuario realmente necesite la funcionalidad.
  • No manejar el estado "denied" permanentemente: En iOS, si un usuario deniega un permiso dos veces, se bloquea permanentemente. Solución: Implementa una pantalla educativa que explique por qué necesitas el permiso y guíe al usuario a configuraciones.
  • Olvidar los strings de Info.plist/Permissions Android: Cada permiso requiere strings de descripción específicos. Solución: Configura correctamente app.json con las entradas ios.infoPlist y android.permissions.
  • Asumir que granted significa funcionalidad disponible: Un permiso puede estar concedido pero el hardware no disponible. Solución: Siempre verifica la disponibilidad del hardware con métodos como isAvailableAsync().
  • No probar flujos de denegación: Solo probar el caso feliz. Solución: Prueba exhaustivamente los flujos donde el usuario deniega permisos o los revoca durante el uso.

Checklist de dominio

  • Puedo implementar el flujo completo de verificación-solicitud-manejo para al menos 3 tipos diferentes de permisos nativos
  • Sé configurar correctamente app.json con los strings de descripción requeridos para iOS y Android
  • Puedo manejar el estado donde el usuario ha denegado permanentemente un permiso y guiarlo a configuraciones
  • Implemento fallbacks apropiados cuando un permiso es denegado o el hardware no está disponible
  • Uso el sistema modular de Expo en lugar de expo-permissions para nuevos proyectos
  • He probado mis flujos de permisos en dispositivos reales tanto en iOS como Android
  • Documento claramente en mi código qué permisos son necesarios y por qué

Implementa un sistema de permisos para una aplicación de notas con multimedia

Crea una aplicación de notas que permita al usuario:

  1. Tomar fotos con la cámara para adjuntar a notas
  2. Grabar audio para notas de voz
  3. Acceder a la galería para seleccionar imágenes existentes
  4. Guardar notas en el almacenamiento local del dispositivo

Pasos detallados:

  1. Configura un nuevo proyecto Expo con los módulos necesarios: expo-camera, expo-av, expo-image-picker, y expo-file-system
  2. Crea un componente NoteEditor que tenga campos para título, contenido y secciones para multimedia
  3. Implementa el manejo de permisos para cámara (fotos y video), micrófono (audio), y almacenamiento (galería y archivos)
  4. Añade botones para cada funcionalidad que verifiquen permisos antes de activarse
  5. Implementa un sistema que muestre mensajes educativos cuando los permisos sean denegados, con opción para ir a configuraciones
  6. Crea un flujo donde el usuario pueda revocar permisos y la aplicación se adapte apropiadamente
  7. Guarda las notas con su multimedia asociada en el almacenamiento local usando expo-file-system
  8. Prueba la aplicación en un dispositivo real o emulador, verificando todos los flujos de permisos
Pistas
  • Usa useEffect para manejar la solicitud de permisos al montar componentes relevantes
  • Implementa un componente PermissionGate que encapsule la lógica de verificación para reutilizar
  • Para el manejo de permisos denegados permanentemente, considera usar Alert.alert con opción para abrir configuraciones

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.

Sigue con Desarrollo Avanzado de Aplicaciones con Expo: De Concepto a Producción

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.