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

Lectura
25 min~5 min lectura

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.