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:
- Importar el módulo específico (ej: expo-camera para permisos de cámara)
- Verificar el estado actual del permiso usando métodos como getPermissionsAsync()
- Si el permiso no está concedido, solicitar acceso con requestPermissionsAsync()
- Manejar la respuesta del usuario apropiadamente
- 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:
- Tomar fotos con la cámara para adjuntar a notas
- Grabar audio para notas de voz
- Acceder a la galería para seleccionar imágenes existentes
- Guardar notas en el almacenamiento local del dispositivo
Pasos detallados:
- Configura un nuevo proyecto Expo con los módulos necesarios: expo-camera, expo-av, expo-image-picker, y expo-file-system
- Crea un componente NoteEditor que tenga campos para título, contenido y secciones para multimedia
- Implementa el manejo de permisos para cámara (fotos y video), micrófono (audio), y almacenamiento (galería y archivos)
- Añade botones para cada funcionalidad que verifiquen permisos antes de activarse
- Implementa un sistema que muestre mensajes educativos cuando los permisos sean denegados, con opción para ir a configuraciones
- Crea un flujo donde el usuario pueda revocar permisos y la aplicación se adapte apropiadamente
- Guarda las notas con su multimedia asociada en el almacenamiento local usando expo-file-system
- Prueba la aplicación en un dispositivo real o emulador, verificando todos los flujos de permisos
- 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.