Saltar al contenido

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

Manejo de permisos y acceso a cámara/geolocalización

Concepto claveEn el desarrollo de aplicaciones móviles, los permisos son el mecanismo mediante el cual tu app solicita acceso a funcionalidades sensibles del dispositivo, como la cámara o la geolocalización. Piensa en ellos como.

Del concepto a la práctica

Taller de esta lección

Un permiso es una decisión del usuario, no una garantía de acceso. Antes de usar cámara o ubicación, comprueba el estado; solicita solo cuando el flujo lo necesita y diferencia concedido, denegado y restringido. Si se deniega, ofrece una salida que no dependa de la capacidad protegida. Todo ensayo debe hacerse en un dispositivo o simulador propio y autorizado.

Ejemplo resuelto

Para la cámara: consulta permiso; al pulsar la acción se solicita si puede preguntarse; granted permite montar la vista previa; denied conserva una descripción manual. La captura tiene manejo independiente de fallo.

Pruébalo

  1. Consulta el permiso actual.

  2. Solicítalo en contexto.

  3. Ejecuta la función solo con autorización.

  4. Maneja cámara ausente o error de captura.

Error frecuente: solicitar cámara y ubicación al abrir la app sin explicar el motivo. Corrige solicitando justo antes de la acción.

Ejercicio: simula denied y granted.

Comprueba tu resultado

el primer caso no llama a la cámara y ofrece alternativa; el segundo intenta capturar y registra el resultado o fallo local.

Cámara actual, denegación y foco

La práctica de esta lección usa cámara; la alternativa manual permite seguir sin capturar. CameraView y useCameraPermissions proceden de expo-camera. Sustituyen el patrón antiguo Camera/expo-permissions del texto histórico. Una concesión permite intentar acceso, pero la cámara puede fallar; no promete una imagen. Este componente representa la vista previa, no captura automáticamente:

jsx
import {useState} from 'react';
import {View,Text,Button,Linking} from 'react-native';
import {CameraView,useCameraPermissions} from 'expo-camera';
export function Camara({enfocada=true}){
  const [permiso,solicitar]=useCameraPermissions();
  const [error,setError]=useState('');
  if(!enfocada) return null;
  if(!permiso) return <Text>Comprobando permiso</Text>;
  if(!permiso.granted) return <View>
    <Text>Puedes continuar con descripción manual.</Text>
    <Text>{error}</Text>
    <Button title={permiso.canAskAgain?'Permitir cámara':'Abrir ajustes'}
      onPress={()=>{setError('');const accion=permiso.canAskAgain?solicitar():Linking.openSettings();accion.catch(()=>setError('No se pudo completar la acción'));}}/>
  </View>;
  return <CameraView style={{flex:1}} facing="back"/>;
}

Solo monta una vista de cámara a la vez y desmóntala cuando deje de estar enfocada; conecta enfocada con el foco real de navegación. No repitas solicitudes cuando canAskAgain=false. La ubicación usa expo-location y su requestForegroundPermissionsAsync independiente: cero es una coordenada válida y accuracy puede ser null. No sustituyas un fallo de GPS por coordenadas ficticias ni solicites fondo para una foto puntual. Camera.

Solicitud de permiso lleva a acceso autorizado o denegado, con alternativa y acceso a ajustes del sistema.
CursaloMapa de práctica
Pide permiso cuando hace falta

Solicita el permiso cuando la tarea lo necesita y explica su propósito. Si se deniega, ofrece una alternativa y respeta la decisión; si el sistema ya no permite volver a solicitarlo, orienta hacia ajustes sin prometer acceso.

Ver la infografía en tamaño completo ↗

Concepto clave

En el desarrollo de aplicaciones móviles, los permisos son el mecanismo mediante el cual tu app solicita acceso a funcionalidades sensibles del dispositivo, como la cámara o la geolocalización. Piensa en ellos como llaves que necesitas para abrir puertas específicas: sin la llave correcta, no puedes acceder a esa habitación (funcionalidad).

En React Native con Expo, el manejo de permisos es especialmente importante porque trabajas con dos plataformas (iOS y Android) que tienen políticas diferentes. Expo simplifica este proceso mediante su API de Permisos, que unifica las diferencias entre plataformas. Una analogía útil: imagina que Expo actúa como un traductor que convierte tu solicitud única en los formatos específicos que entienden iOS y Android.

Existen dos momentos clave para solicitar permisos: en tiempo de instalación (algunos permisos se piden cuando el usuario instala la app) y en tiempo de ejecución (cuando el usuario intenta usar una funcionalidad por primera vez). La mejor práctica es solicitar permisos justo cuando el usuario los necesita, no todos al inicio.

Cómo funciona en la práctica

El flujo típico para manejar permisos en Expo sigue estos pasos:

  1. Verificar el estado actual del permiso usando Permissions.getAsync()
  2. Si el permiso no está concedido, solicitar al usuario con Permissions.askAsync()
  3. Manejar la respuesta del usuario (granted, denied, o undetermined)
  4. Si es granted, proceder con la funcionalidad (ej: abrir cámara)
  5. Si es denied, mostrar una explicación y opción para ir a configuración

Para la cámara, Expo proporciona el componente Camera que requiere el permiso CAMERA. Para geolocalización, usas Location que requiere LOCATION. Cada módulo tiene su propia API pero comparten el patrón de permisos.

Código en acción

Veamos un ejemplo completo de solicitud de permiso para cámara:

import React, { useState, useEffect } from 'react';
import { View, Text, Button, Alert } from 'react-native';
import { Camera } from 'expo-camera';
import * as Permissions from 'expo-permissions';

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

  useEffect(() => {
    checkCameraPermission();
  }, []);

  const checkCameraPermission = async () => {
    const { status } = await Permissions.getAsync(Permissions.CAMERA);
    setHasPermission(status === 'granted');
  };

  const requestCameraPermission = async () => {
    const { status } = await Permissions.askAsync(Permissions.CAMERA);
    if (status === 'granted') {
      setHasPermission(true);
    } else {
      Alert.alert(
        'Permiso necesario',
        'Necesitamos acceso a la cámara para tomar fotos.',
        [
          { text: 'Cancelar', style: 'cancel' },
          { text: 'Abrir configuración', onPress: () => Linking.openURL('app-settings:') }
        ]
      );
    }
  };

  if (hasPermission === null) {
    return Solicitando permiso...;
  }
  if (hasPermission === false) {
    return (
      
        No tenemos acceso a la cámara
        
      
    );
  }
  return (
     setCameraRef(ref)}>
      {/* Controles de cámara aquí */}
    
  );
}

Ahora, un ejemplo mejorado que maneja múltiples permisos (cámara y ubicación):

import * as Permissions from 'expo-permissions';

const requestMultiplePermissions = async () => {
  const { status: cameraStatus } = await Permissions.askAsync(Permissions.CAMERA);
  const { status: locationStatus } = await Permissions.askAsync(Permissions.LOCATION);
  
  return {
    camera: cameraStatus === 'granted',
    location: locationStatus === 'granted'
  };
};

// Uso en tu componente:
const permissions = await requestMultiplePermissions();
if (permissions.camera && permissions.location) {
  // Ambos permisos concedidos
} else {
  // Manejar permisos faltantes
}

Errores comunes

  • Solicitar todos los permisos al inicio: Esto molesta a los usuarios y reduce las tasas de conversión. En su lugar, solicita permisos justo cuando el usuario intenta usar la funcionalidad.
  • No manejar el estado "undetermined": En iOS, algunos permisos inician como "undetermined". Si no manejas este caso, tu app puede quedar bloqueada.
  • Olvidar el permiso de ubicación en segundo plano: Para apps que necesitan ubicación continua, necesitas LOCATION_BACKGROUND además de LOCATION.
  • No probar en ambos sistemas: Android e iOS manejan los permisos diferente. Siempre prueba en ambas plataformas.
  • Ignorar el rechazo del usuario: Si el usuario niega un permiso, debes mostrar una explicación útil y una forma de cambiar la decisión desde configuración.

Checklist de dominio

  • Puedo solicitar permisos para cámara usando expo-permissions y expo-camera
  • Sé solicitar permisos para geolocalización con expo-location
  • Manejo correctamente los tres estados de permiso: granted, denied, undetermined
  • Implemento solicitud de permisos en el momento adecuado (just-in-time)
  • Proveo flujos alternativos cuando el usuario niega permisos
  • He probado el comportamiento en simuladores de iOS y Android
  • Entiendo las diferencias entre permisos en tiempo de instalación vs tiempo de ejecución

App de fotos con geolocalización

Crea una aplicación que permita tomar fotos y guardarlas con su ubicación geográfica. Sigue estos pasos:

  1. Crea un nuevo proyecto Expo: expo init PhotoGeoApp
  2. Instala las dependencias necesarias: expo install expo-camera expo-location expo-permissions
  3. Crea un componente principal que tenga:
    • Un botón para activar la cámara
    • Un botón para tomar foto
    • Un indicador de ubicación actual
  4. Implementa la lógica de permisos:
    • Solicita permiso de cámara solo cuando el usuario presione el botón de activar cámara
    • Solicita permiso de ubicación al iniciar la app, pero si es denegado, vuelve a preguntar cuando el usuario intente tomar una foto
  5. Al tomar una foto:
    • Obtén la ubicación actual
    • Guarda la foto con metadatos de ubicación (puedes usar console.log para simular el guardado)
    • Muestra un mensaje con las coordenadas donde se tomó la foto
  6. Maneja los casos de error:
    • Si no hay permiso de cámara, muestra un mensaje explicativo
    • Si no hay permiso de ubicación, guarda la foto sin ubicación pero informa al usuario

Entrega el código completo de App.js y cualquier componente adicional que hayas creado.

Pistas
  • Usa el hook useEffect para solicitar permisos de ubicación al montar el componente
  • Para la cámara, implementa un estado booleano que controle si se muestra o no el componente Camera
  • Recuerda que Location.getCurrentPositionAsync puede fallar si no hay GPS disponible, maneja ese caso con try-catch

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.

Sigue con React Native y Expo: Interfaces, Estado y APIs de Dispositivo

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.