On the open web, a single click lets a page use navigator.bluetooth to request a nearby Bluetooth Low Energy (BLE) device, connect to its GATT server, and read or write characteristics. Inside a WebView that entry point simply does not exist. Android WebView does not expose navigator.bluetooth at all — the property is undefined — and the MDN browser-compatibility data records WebView (Android) as "No". On iOS the situation is more subtle: neither Safari nor WKWebView ships Web Bluetooth, and because every iOS browser is forced to use the WebKit engine, Chrome and Edge on iOS inherit the same gap. WebKit has filed an "opposed" standards position on the spec, so there is no in-flight implementation to wait for.
For a WebView page the result is uniform across engines: the code that works on the desktop web throws or no-ops, and there is no fallback inside the page.
Even where it exists, it is fragile
It is worth noting that Web Bluetooth is delicate even on the browsers that do support it. Chrome requires a secure context (HTTPS), a transient user activation (the call must come from a click, not a timer or fetch handler), and it maintains a built-in blocklist that hides some vendor and product IDs — including some FIDO and HID classes — before the chooser ever opens. A page that depends on it is already one permission prompt and one flag away from breaking. In a WebView there is no browser to fall back to, so the capability is simply gone.
What breaks when hardware pairing dies
- Hardware security keys cannot pair. A broker or exchange that lets users confirm withdrawals with a BLE FIDO authenticator cannot complete that flow from a WebView page — the authenticator is invisible to the page.
- Hardware wallets stay disconnected. Crypto and OTC desks that pair a hardware wallet to verify addresses or sign transactions have no path from embedded web content.
- Peripheral terminals fail. BLE receipt printers, scanners, and POS accessories that a merchant mini-program relies on cannot be reached.
- Silent, not loud. Because the API is
undefined(or, on iOS, never prompts), the failure is a quiet no-op — no error the user can act on, just a button that does nothing.
The runtime fix
A host-owned runtime bridges the Bluetooth layer. The page calls one uniform API — runtime.connectBle({ filters, onData }) — and the host resolves it through the platform-native Bluetooth stack: Android BluetoothGatt over BluetoothAdapter, or iOS CoreBluetooth (CBCentralManager, CBPeripheral). Pairing, service discovery, and characteristic I/O are handled natively and consistently. One integration, every engine, real hardware at the end of it.
| Dimension | WebView | Host-owned runtime |
|---|---|---|
navigator.bluetooth | undefined (Android WebView); absent (iOS WKWebView) | Native BLE via CoreBluetooth / Android Bluetooth |
| Secure context + gesture | Required even where supported | Host-triggered; no fragile activation token |
| Device classes | Chrome blocklist hides some FIDO/HID | Full GATT access to paired peripherals |
| Hardware wallet / security key | Cannot pair | Native pairing + signed response |
| Receipt printer / scanner | Cannot connect | Native connection, reliable |
| Consistency | Per-engine, mostly missing | Uniform |
A native app pairs a BLE security key on every device. A stock WebView pairs it on almost none. A runtime gives the page one connect call — and a real peripheral at the end of it.
Sources
- openpwa — Web Bluetooth API — Android WebView does not expose
navigator.bluetooth; WebKit records an "opposed" standards position. - MDN Web Docs — Web Bluetooth API — browser-compatibility data records WebView (Android) as not supported.
- Chrome Developers — Communicating with Bluetooth devices — secure-context, transient user-activation, and built-in blocklist requirements.
- WebKit Standards Positions — WebKit's opposed position; no WebKit implementation of Web Bluetooth.
- Median docs — Web Bluetooth in WebView — "not supported by iOS WebKit or Android WebView."