Introducing AI Conversations: Natural Language Interaction for Your Apps! Learn More
BluetoothLE Releases
5.0.0 - TBD
Section titled “5.0.0 - TBD” Feature
L2CapChannelExtensions.SendFile(...) — new file-transfer helper on top of an open L2CapChannel with HTTP-transfer-style progress metrics (bytes-per-second, percent-complete, estimated time remaining). Overloads accept either a file path (length auto-detected) or an arbitrary Stream with an optional totalBytes. Progress callbacks fire ~every 2s plus a final 100% emission on completion. The new Shiny.BluetoothLE.TransferProgress record mirrors Shiny.Net.Http.TransferProgress so consumers have an identical mental model across HTTP and L2CAP transfers. Lives in Shiny.BluetoothLE.Common, shared with the hosting library. Feature
L2CAP CoC central-role support shipped via the optional
ICanL2Cap capability on IPeripheral. Call peripheral.OpenL2CapChannel(psm, secure) (or the safe TryOpenL2CapChannel(...) extension on the base IPeripheral) to open a streaming channel to a peripheral that has published a PSM. Supported on iOS, Mac Catalyst, macOS (CoreBluetooth CBPeripheral.OpenL2CapChannel), Android API 29+ (BluetoothDevice.CreateL2capChannel / CreateInsecureL2capChannel), and Linux (BlueZ — raw AF_BLUETOOTH / BTPROTO_L2CAP / SOCK_SEQPACKET socket; LE dynamic PSMs ≥ 0x80 do not need CAP_NET_RAW). On Apple platforms the secure flag is ignored — security is determined by how the peripheral published the channel. On Linux the flag toggles BT_SECURITY_LOW/MEDIUM via setsockopt(SOL_BLUETOOTH, BT_SECURITY). Enhancement
The public
L2CapChannel record moved into Shiny.BluetoothLE.Common (namespace Shiny.BluetoothLE) so both central and hosting libraries share one type. The record now implements IDisposable with an optional OnDispose hook for closing streams and disposing sockets. Fix Android
Shiny.BluetoothLE.Extensions.ListenForData(BluetoothSocket) now reads from socket.InputStream (was incorrectly reading OutputStream) and emits a right-sized copy of each chunk instead of the full 8 KB buffer. The observable now completes on EOF and surfaces read errors via OnError. Fix iOS
Shiny.BluetoothLE.Extensions.ListenForData(NSInputStream) now drains all bytes available per HasBytesAvailable event, emits a right-sized copy per read (was leaking the full 8 KB shared buffer to every subscriber), and completes on NSStreamEvent.EndEncountered. Feature
macOS support added via CoreBluetooth (central role) -
Shiny.BluetoothLE Feature
Linux support added via BlueZ / D-Bus (central role) - new
Shiny.BluetoothLE.Linux package Feature
Blazor WebAssembly (Web) support added via the browser Web Bluetooth API - new
Shiny.BluetoothLE.Blazor package. Central role only; scans require a user gesture, HTTPS, and a Chromium-based browser Fix Windows
Fix BLE state cleanup after disconnect and reconnect - properly releases GATT resources and disposes stale peripherals
Fix Android
Fix the classic “status 133 after a few reconnects” trap —
Connect() now closes any prior BluetoothGatt before opening a new client, so reconnect loops no longer leak GATT clients into Android’s per-app limit. Fix Android
Connection state and connection-failure observables are now replay-safe (
BehaviorSubject / time-windowed ReplaySubject), so subscribers that hook up immediately after calling Connect() no longer miss the resulting state change or failure. Fix Android
OnConnectionStateChange now dispatches subscriber notifications off the single-threaded GATT binder callback thread, removing a class of deadlocks where awaiting subscribers blocked further BLE callbacks. Fix Android
Notifier teardown re-resolves the characteristic against the current
BluetoothGatt instead of a captured (possibly closed) reference, preventing spurious status 133 errors on the next operation after a disconnect/reconnect cycle. Fix Android
Starting a scan no longer evicts peripherals that are currently in the
Connecting state. Fix iOS
IBleManager.GetKnownPeripheral(uuid) now calls CoreBluetooth’s RetrievePeripheralsWithIdentifiers, so callers can reconnect to a previously-paired device by UUID after a process restart without first running a scan. Fix iOS
IBleManager.GetConnectedPeripherals() now seeds from RetrieveConnectedPeripherals so devices connected by other apps or restored sessions are visible. Fix iOS
Auto-reconnect now issues
CancelPeripheralConnection before each retry (iOS otherwise holds the previous pending connection slot) and additionally retries on FailedToConnectPeripheral, fixing cold-start failures that previously never retried because no Disconnected event was emitted. Fix Windows
Service and characteristic lookups on the hot path now use
BluetoothCacheMode.Uncached, so a reconnect always re-discovers fresh GattDeviceService / GattCharacteristic handles instead of silently operating on dead, OS-cached ones. Fix Windows
Peripheral connections now acquire a
GattSession with MaintainConnection = true, so the OS keeps the LE link up across idle periods and automatically re-establishes it when a device returns in range — eliminating “the connection dropped while idle” symptoms. Fix Windows
IPeripheral references now survive a disconnect/reconnect cycle. Previously the manager replaced the wrapper instance on every reconnect, leaving any caller-held reference dead with “Device is disposed” errors. The wrapper now refreshes its underlying BluetoothLEDevice in place. Fix Windows
A transient
ConnectionStatus = Disconnected dip immediately after a successful service discovery no longer cancels the connect attempt — the connect now succeeds, and a real subsequent disconnect is handled by the normal ConnectionStatusChanged path.4.0.0 - March 26, 2026
Section titled “4.0.0 - March 26, 2026” Feature
Windows support added (No Background Support at this time)
Enhancement
ManagedScanResult is now passed with the full advertisement data in case user needs access to native internals
Enhancement Android
Improved manufacturer data parsing in ad data
Fix
ManagedScan now uses thread safe BindingList
Fix Android
BLE scan now disables legacy scanning for new android versions
Fix Android
BLE Delegate was not responding with Available when adapter was reenabled
3.3.4 - April 22, 2024
Section titled “3.3.4 - April 22, 2024” Fix Android
Disable legacy scanner on newer Android versions
Fix Android
ManagedScanResult now has a property for the raw advertisement data
Fix Android
Additional thread safety on managed scan events
3.3.0 - March 18, 2024
Section titled “3.3.0 - March 18, 2024” Fix Android
IBleDelegate now reports adapter state properly
Fix Android
Unsubscribing from a connection may be temporarily unstable if sub/unsub is performed rapidly
Fix Android
Reduce logging severity for characteristic events
Fix
Characteristic extension (GetAllCharacteristics) was only returning characteristics from last service
3.2.0 - December 8, 2023
Section titled “3.2.0 - December 8, 2023” Enhancement
BLE manager now allows you to check current permissions without requesting
3.0.0 - September 5, 2023
Section titled “3.0.0 - September 5, 2023” Enhancement Android
RequestAccess(bool connect) now allows you to additionally request access to GATT connections (defaults to true). This allows Shiny to use Android API 31 properly. It will always ask for scan permissions.
BREAKING Android
Adapter control is no longer support through the Shiny API, but you do have raw access to the native adapter if needed
BREAKING
Managed scan now require you to set scan configuration values in Start instead of the constructor & property setters
BREAKING
The API has been simplified and no longer requires you to maintain (and refresh) instances of services/characteristics/descriptors
BREAKING
Managed peripheral is now gone. This functionality is now built into the main API.
BREAKING Enhancement Android
Android MTU requests are moved to the IPeripheral.Connect(AndroidConnectionConfig)