El audio y vídeo en vivo sobre WebRTC es de primera clase en la web móvil, hasta que corre dentro de un WebView. En Android, la decisión de permiso de getUserMedia se delega al host mediante onPermissionRequest, y en iOS WKWebView trae la captura de medios desactivada por defecto. La mayoría de los navegadores integrados nunca conectan una llamada. Un runtime propio del host hace la ponte de los medios en tiempo real: una API para cámara, micrófono y conexión peer en cada motor.

Android: la decisión de permiso está en el host

Cuando la página llama navigator.mediaDevices.getUserMedia, el WebView no pregunta al usuario; llama a WebChromeClient.onPermissionRequest y el host otorga o deniega. Antes de otorgar, el host debe solicitar los permisos de runtime CAMERA y RECORD_AUDIO y, idealmente, verificar el origen. Si esa cadena no está conectada, el log muestra CheckMediaAccessPermission: Not supported y getUserMedia rechaza en silencio con NotAllowedError. La documentación de Android es clara: solicita el permiso de runtime antes de grant(). Así que si la llamada en vivo conecta depende totalmente de que el contenedor implemente la ponte.

iOS: la captura de medios está desactivada por defecto

iOS 11 trajo WebRTC a Safari, pero WKWebView no habilita la captura por defecto. Una app de terceros debe configurarla: añadir NSCameraUsageDescription y NSMicrophoneUsageDescription al Info.plist, fijar allowsInlineMediaPlayback = true y mediaTypesRequiringUserActionForPlayback = [], y en iOS 14+ permitir la captura con WKMediaCapturePermissionsPolicy. Aun así, navegadores integrados como WeChat, Douyin y Facebook a menudo no la habilitan, así que getUserMedia reporta not found. Más allá de la captura, el SDK web de Agora señala que iOS Safari y WKWebView no soportan getDisplayMedia (compartir pantalla), y al pasar a segundo plano AVCaptureSession no puede usar la cámara, por lo que el remoto ve un fotograma negro; el control de fps vía RTCRTPSender.setParameters tampoco está disponible.

Qué se rompe cuando la llamada se calla

  • Soporte por vídeo y telemedicina se estancan. La llamada nunca obtiene la cámara.
  • Salas de voz y live co-streaming en silencio. Ningún flujo de micrófono llega al par.
  • Compartir pantalla no disponible. getDisplayMedia no se soporta en iOS WebView.
  • Pasar a segundo plano corta la llamada. La cámara se pone negra.
  • Safari funciona, WebView no. Una página que conecta en Safari falla en el navegador integrado del mismo dispositivo.

La solución del runtime

Un runtime propio del host hace la ponte de la capa de medios en tiempo real. Envuelve getUserMedia con permisos nativos de cámara y micrófono y expone una API uniforme para cámara, micro y conexión peer. El host gestiona un RTCPeerConnection estable —STUN/TURN compartidos, manejo ICE y negociación de códec de hardware (H.264/VP8)— para que la llamada en vivo conecte en cada motor. El permiso se pide una vez, de forma nativa; el flujo y la conexión son consistentes.

DimensiónWebViewRuntime propio del host
Permiso AndroidonPermissionRequest del hostConcesión nativa
Captura iOSDesactivada por defectoHabilitación nativa
Compartir pantallagetDisplayMedia no soportadoPonte nativa
Cámara en segundo planoFotograma negroSesión gestionada
Conexión peerPor motorUniforme
ConsistenciaPor motorUniforme

Una app nativa ejecuta una videollamada en cada teléfono. Un WebView estándar apenas en ninguno. Un runtime da a la página una superficie de medios — y un par en vivo al otro lado.

Fuentes