Cuando un cliente me pidió que su PWA, instalada desde la pantalla de inicio en un iPhone, pudiera usar la cámara, pensé: ‘Pan comido, si es web, es web’. Pero la realidad de iOS 11 me golpeó fuerte. La cámara simplemente no funcionaba, ni con WebRTC ni con el típico input de archivo. Imagínate la frustración.
Esto no era un problema de mi código, sino una limitación impuesta por Apple en las web apps que se ejecutan en modo 'standalone'. Es decir, esas que agregas a la pantalla de inicio con la meta etiqueta apple-mobile-web-app-capable. Safari como navegador completo, sin problemas. Pero en su versión «aplicación», ni hablar. Lo peor es que esto nos pasó a varios, y las soluciones en ese entonces eran o un parche o un cambio de paradigma.
El Problema: WebKit en Standalone vs. Safari Completo
La raíz del problema estaba en cómo Apple maneja el motor de renderizado WebKit. Cuando abres una PWA que has añadido a la pantalla de inicio, no se ejecuta en el mismo entorno que Safari. En su lugar, usa un UIWebView o WKWebView, que son componentes más restrictivos. Y claro, las funcionalidades como el acceso a la cámara y micrófono vía getUserMedia o incluso un simple <input type="file" accept="image/*" capture="camera">, estaban capadas.
Esto me generó una rabia tremenda, porque ¿cuál es el punto de tener PWA si no puedes usar capacidades básicas del dispositivo? La promesa de las PWA es que sean lo más cercanas posible a una app nativa, pero este tipo de restricciones te tiraban por la borda cualquier esfuerzo. De hecho, recuerdo una discusión acalorada con un colega donde él defendía que «eso pasa por no hacer una app nativa», y yo, por mi lado, diciendo que el estándar web debe funcionar en todos lados. Al final, ambos teníamos un poco de razón.
El código para activar esto, que muchos usábamos, se veía así:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mi PWA con Cámara</title>
<!-- La etiqueta que causaba el problema en iOS 11 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- ... otros meta tags y enlaces a manifest.json -->
</head>
<body>
<h1>Bienvenido a mi PWA</h1>
<input type="file" accept="image/*" capture="camera" id="cameraInput">
<video id="video" autoplay></video>
<script>
const cameraInput = document.getElementById('cameraInput');
cameraInput.addEventListener('change', (event) => {
const file = event.target.files[0];
if (file) {
console.log('Archivo de imagen capturado:', file.name);
// Aquí podrías subir la imagen o mostrarla
}
});
// Esto no funcionaba en iOS 11 standalone, solo en Safari completo
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
const video = document.getElementById('video');
video.srcObject = stream;
})
.catch(err => {
console.error("Error al acceder a la cámara:", err);
});
</script>
</body>
</html>
Si probabas el código de arriba en iOS 11 en una PWA añadida a la pantalla de inicio, el getUserMedia fallaba y el input type="file" simplemente no abría la cámara, solo el selector de fotos. Un desastre.
Las Soluciones (o Parches) que Encontramos
En ese momento, las opciones eran limitadas y ninguna me terminaba de convencer.
1. Sacar la Meta Etiqueta: El Mal Menor
La solución más común y la que más me gusta por su simplicidad —aunque a regañadientes— fue eliminar la etiqueta <meta name="apple-mobile-web-app-capable" content="yes">. ¿Qué lograbas con esto? Que cuando el usuario intentaba abrir la “aplicación” desde la pantalla de inicio, en lugar de ejecutarse como una PWA standalone, se abría directamente en Safari.
Sí, perdías la experiencia de “app sin navegador”, pero al menos recuperabas la funcionalidad de la cámara. Para el cliente que quería que su PWA pudiera escanear códigos o tomar fotos de documentos, esto era un compromiso necesario. No era lo ideal, pero funcionaba, y en mi experiencia, lo que funciona y es simple, es lo que vale al final del día. Ojo que muchos usuarios ni se daban cuenta de la diferencia real, más allá de la barra de navegación de Safari.
2. Apache Cordova: Sobreingeniería para una PWA
Otra opción que salió a flote era encapsular la web app en un framework híbrido como Apache Cordova. Esto te permitía crear una app nativa que renderizaba tu webview y te daba acceso a las APIs del dispositivo (incluida la cámara) a través de plugins.
Personalmente, no me convence para una PWA. Si ya estás construyendo una PWA, la idea es evitar la complejidad de un wrapper nativo. Meter Cordova para algo que debería funcionar nativamente en el navegador web me parece sobreingeniería pura. Si el proyecto requería ir por ese camino, ¿por qué no hacer una app nativa desde el principio? No hay que dar más vueltas de las necesarias.
La Luz al Final del Túnel: iOS 11.3
Afortunadamente, Apple rectificó. Con la llegada de iOS 11.3, las cosas cambiaron. Apple, como a veces hace, corrigió esta limitación y habilitó el acceso a la cámara para las web apps instaladas en la pantalla de inicio. Esto fue un alivio tremendo para muchos developers que nos quedamos con el pelo en la mano por meses.
Esto me recuerda que en el desarrollo, y más con ecosistemas cerrados, a veces toca esperar a que el proveedor de la plataforma se ponga las pilas. No siempre tenemos el control, y entender eso me costó un poco al principio de mi carrera. Quería arreglarlo todo, pero a veces la solución está en un update que no depende de ti.
Mi Opinión y Recomendación Final
El episodio de la cámara en PWA de iOS 11 fue una muestra clara de las batallas que enfrentamos cuando intentamos empujar los límites del desarrollo web en plataformas que no siempre juegan limpio con los estándares. Apple siempre ha tenido su ecosistema muy cerrado, y esto fue un ejemplo más.
Si hoy me encuentro con un proyecto donde la cámara es una funcionalidad crítica para una PWA en iOS, mi recomendación es clara:
Asumiendo que tus usuarios tienen versiones de iOS actuales (11.3 en adelante), no necesitas hacer nada especial; la cámara debería funcionar correctamente con las APIs web estándar. Mantén el <meta name="apple-mobile-web-app-capable" content="yes"> si quieres la experiencia de app standalone.
Pero si, por alguna razón, tienes que soportar usuarios con iOS 11.0-11.2 (lo cual es raro hoy, pero puede pasar en entornos corporativos o con dispositivos antiguos), entonces lo más sensato es quitar la etiqueta <meta name="apple-mobile-web-app-capable" content="yes">. Perderás un poco de la magia de la PWA, pero ganarás la funcionalidad de la cámara al forzar la apertura en Safari. Es el camino más simple y directo para asegurar que la funcionalidad crítica esté disponible, sin añadir capas de complejidad innecesarias como Cordova. Siempre busco la solución que funcione con el menor número de piezas móviles.