En la web abierta, un clic basta para que una página use navigator.bluetooth y solicite un dispositivo BLE cercano, se conecte a su servidor GATT y lea o escriba características. Pero dentro de un WebView ese punto de entrada simplemente no existe. Android WebView no expone navigator.bluetooth —la propiedad es undefined— y los datos de compatibilidad de MDN marcan WebView (Android) como "no soportado". En iOS la situación es más sutil: ni Safari ni WKWebView implementan Web Bluetooth, y como iOS obliga a todos los navegadores a usar el motor WebKit, Chrome y Edge en iOS heredan la misma brecha. WebKit registra una posición "opuesta" sobre la especificación, así que no hay ninguna implementación en camino.

Para una página WebView el resultado es uniforme entre motores: el código que funciona en la web de escritorio lanza error o no hace nada, y la página no tiene ningún respaldo interno.

Incluso donde existe, es frágil

Vale la pena señalar que Web Bluetooth es delicado incluso en los navegadores que lo soportan. Chrome exige un contexto seguro (HTTPS), una activación transitoria del usuario (la llamada debe venir de un clic, no de un temporizador o un fetch) y mantiene una lista negra integrada que oculta algunos IDs de proveedor y producto —incluidas algunas clases FIDO y HID— antes de que se abra el selector. Una página que depende de él ya está a un aviso de permiso y un flag de distancia de romperse. En un WebView no hay navegador al que recurrir, así que la capacidad simplemente desaparece.

Qué se rompe cuando el emparejamiento de hardware muere

  • Las llaves de seguridad BLE no se emparejan. Un bróker o exchange que confirma retiros con un autenticador FIDO BLE no puede completar ese flujo desde una página WebView: el autenticador es invisible para la página.
  • Los monederos de hardware quedan desconectados. Los mostradores de cripto y OTC que emparejan un monedero de hardware para verificar direcciones o firmar transacciones no tienen ninguna vía desde el contenido web embebido.
  • Las terminales periféricas fallan. Las impresoras de recibos BLE, los escáneres y los accesorios POS que usa un mini-programa de comerciante no se pueden alcanzar.
  • Silencioso, no ruidoso. Como la API es undefined (o, en iOS, nunca muestra el aviso), el fallo es un no-op silencioso: sin error que el usuario pueda manejar, solo un botón que no hace nada.

La solución en el runtime

Un runtime propio del host conecta la capa Bluetooth. La página llama a una sola API uniforme —runtime.connectBle({ filters, onData })— y el host la resuelve con la pila Bluetooth nativa de la plataforma: Android BluetoothGatt sobre BluetoothAdapter, o iOS CoreBluetooth (CBCentralManager, CBPeripheral). El emparejamiento, el descubrimiento de servicios y la E/S de características se manejan de forma nativa y coherente. Una integración, todos los motores, hardware real al final.

DimensiónWebViewRuntime propio del host
navigator.bluetoothundefined (Android WebView); ausente (iOS WKWebView)BLE nativo vía CoreBluetooth / Android Bluetooth
Contexto seguro + gestoRequerido incluso donde hay soporteActivado por el host; sin token frágil
Clases de dispositivoLa lista negra de Chrome oculta FIDO/HIDAcceso GATT completo a periféricos emparejados
Monedero / llave de seguridadNo se emparejaEmparejamiento nativo + respuesta firmada
Impresora / escánerNo se conectaConexión nativa, fiable
ConsistenciaPor motor, mayormente ausenteUniforme

Una app nativa empareja una llave BLE en todos los dispositivos. Un WebView estándar no lo hace en casi ninguno. Un runtime le da a la página una sola llamada connect —y un periférico real al final.

Fuentes