universal_ble 3.0.2
universal_ble: ^3.0.2 copied to clipboard
A cross-platform (Android/iOS/macOS/Windows/Linux/Web) Bluetooth Low Energy (BLE) plugin for Flutter
3.0.2 #
- Fix the broken "Try it online" demo URL in the README.
3.0.1 #
- Bump
flutter_web_bluetoothto^1.2.0. - Web: use the dependency's advertisement abort controller and
startupTimeoutinstead of the hand-rolled abort/timeout workaround.unwatchAdvertisementsnow also aborts a pending advertisement startup.
3.0.0 #
- Breaking: Add
QueueType.autowhich auto-selects the best queueing strategy per platform: Android, Web, and Linux use a per-device queue (their BLE stacks reject or misbehave on overlapping operations), while all other platforms run commands in parallel. It is now the default for bothUniversalBleandUniversalBlePeripheral, replacing the previousQueueType.globaldefault. Any exhaustiveswitchoverQueueTypemust handle the newautovalue. - Breaking: Device IDs are now emitted in lower-case on every platform (scan results, connection/value/pairing/connection-parameter callbacks and streams). Previously each platform reported its native case — Android upper-cased MACs, Windows/WinRT lower-cased them. IDs are now canonicalised to lower-case throughout the Dart layer; the native side converts back to the case it requires at its boundary (Android's
getRemoteDeviceneeds upper-case). Callers that stored or compared an emitted ID by exact case (e.g. an Android upper-case MAC) must now lower-case it, or compare case-insensitively. Web is exempt: Web Bluetooth IDs are opaque, case-sensitive browser tokens rather than addresses, so they are emitted and matched verbatim. Follow-up to the case-insensitive matching in 2.1.1. CustomUniversalBlePlatformimplementations must report the canonical form too: the event-stream filters now match the canonical id directly, so a platform that pushes a non-canonical id straight onto the exported stream controllers (instead of calling theupdate*handlers, which canonicalise) will no longer match a query made with a different casing. The same applies to peripheral mode: central device IDs inUniversalBlePeripheralstreams, read/write request handlers, andgetSubscribedClientsresults are emitted in lower-case, and IDs passed toupdateCharacteristicValue/getMaximumNotifyLengthare accepted in any case. - Breaking:
onConnectionChangenow receives a singleBleConnectionChange(deviceId,isConnected,error) instead of three positional arguments. It also carries a unifiederrorCode(UniversalBleErrorCode.deviceDisconnected,connectionTimeout,connectionFailed, ...) and the rawnativeErrorCode(CBError.Codeon Apple, GATT status on Android); a connection attempt that never succeeds isconnectionFailedon both. AddconnectionChangeStreamandBleDevice.connectionChangeStreamemitting the same updates per device;connectionStreamis unchanged.UniversalBlePlatform.bleConnectionChangeStreamController(internal) now carriesBleConnectionChangeinstead of a record. - Breaking:
onValueChangenow receives a singleBleCharacteristicValue(deviceId,characteristicId,value,timestamp) instead of four positional arguments. - Breaking: Rename
BleConnectionParametersUpdatedtoBleConnectionParametersChange, aligning the payload with the…Changeevent naming. TheonConnectionParametersChangecallback and the model's fields are unchanged. - Breaking: On iOS 18+
unpairnow removes an accessory authorized through AccessorySetupKit (it previously threwnotSupportedon iOS). Devices not managed by AccessorySetupKit fail withdeviceNotFound. - iOS/macOS/Web:
onPairingStateChange/pairingStateStreamnow fire. These platforms have no native bond API, sopair()drives them from its encrypted-characteristic probe:truewhen the probe succeeds, a failure event (false) when it throws. Without apairingCommandthe probe reads every readable characteristic and now fails if none can be read, rather than resolving successfully. The 0.12.0 changelog claimed this support, but the callback was never actually wired on those platforms until now. requestMtunow discovers the device's services on demand on iOS/macOS and Linux, instead of returning a misleading MTU (Apple reported the default ATT MTU, 23, as if it were the negotiated value) or failing with an unclearoperationNotSupported(Linux). It is a no-op when the services were already discovered, so callingdiscoverServicesfirst still works and is not required, and concurrent calls (including one racing adiscoverServices) share a single discovery.timeoutbounds each step, so a call that must discover first can take up to roughly twicetimeout. Android and Windows read the MTU off the connection itself and are unchanged. AddBleCapabilities.mtuRequiresServiceDiscovery.- Add
requestDevice, a single entry point for the platform's native device picker: the browser's Bluetooth chooser on Web and the iOS 18+ AccessorySetupKit picker on Apple (configured viaPickerPlatformConfig.apple), returning the selectedBleDevice. Connect it with the existingconnect(device.deviceId).AppleAccessorySetupOptionsholds a list ofAppleAccessoryPickerItems, so the picker can offer several accessories. Platforms without a native picker thrownotSupported. - Windows: enable extended BLE advertisement scanning (
AllowExtendedAdvertisements), with graceful fallback on unsupported OS versions or adapters. - Add
skipDuplicatestostartScanto report each device only once per scan session — later sightings, including ones whose advertisement payload changed, are suppressed until the scan is restarted. Native filtering is applied where available (iOS/macOS, AndroidScanSettings, Linux BlueZDuplicateData) and the Dart layer de-duplicates on every platform so the behavior is consistent everywhere. Defaults tofalse(unchanged). - Add
connectableproperty toBleDevice. - Add
connectableOnlytoScanFilterto filter for connectable devices during scanning. - Windows: Expose non-connectable devices during scanning to match other platforms.
- Windows: deliver scan responses as scan results. A peripheral that publishes its 128-bit service UUID in the scan response (it does not fit in the advertisement next to the name) was invisible to
startScan: Windows reports that packet withIsConnectable == falseand it was dropped before reaching the caller. - Enhance
Uint8ListandFuture<Uint8List>extensions with comprehensive BLE data type conversions (int8,uint8,int16,uint16,int32,uint32,float32,float64,toUtf8,toHexString), byte offset support, and directbyteDataview accessor. - Add
UniversalBle.canonicalDeviceId(deviceId), which returns a device ID in the comparable form for the current platform (lower-case on native platforms, verbatim on Web) — for keying a map or comparing IDs yourself. - Add
subscribedCentralsStreamandsubscribedCentralsgetter toUniversalBlePeripheralto track and expose active central devices (BleCentral) subscribed to characteristics in peripheral mode. - Add
platformConfigtodiscoverServices();AndroidDiscoverServicesOptions(clearGattCache: true)clears Android's GATT cache (BluetoothGatt.refresh()) before discovery. Ignored on other platforms. - Add
universal_blepackage skills installable withdart run skills@ get:universal-ble-setup(add BLE to an app from scratch),universal-ble-migrate-2-to-3(upgrade from 2.x), anduniversal-ble-migrate-from-flutter-blue-plus(migrate fromflutter_blue_plus). - Android/iOS/macOS/Windows: keep the GATT client cache per plugin instance (one per FlutterEngine). It was process-wide, so a
connect()from one engine could short-circuit on a client created by a destroyed engine — returning a connection that reported as connected but whose service discovery came back empty. Each engine now sees only its own clients, andcloseGattOnDetachreleases only the clients the detaching engine created instead of every client in the process. - Android: Register MTU waiters before the native request, serialize completions onto the main looper, and fail rejected requests immediately.
- Android: Reuse an MTU already negotiated on the current GATT connection; isolate reconnects from late callbacks.
- Android: report every failed bond — including a declined system-initiated bond that ends in
BOND_NONE— not only the first per process. A failed pairing attempt is an event rather than a state, soonPairingStateChangeno longer de-duplicates it against the cached pairing state (#325). - iOS/macOS: Handle write-without-response transmit buffer backpressure
- iOS/macOS: complete concurrent reads, descriptor operations, notification changes, and RSSI reads one callback at a time.
- Windows: dispose disconnected WinRT GATT objects on a background MTA thread to avoid blocking the UI during teardown.
- Windows: retry transiently unreachable GATT service discovery during connection.
- Windows: fix crashes when closing the app while Bluetooth initialization is still pending.
- Extend Windows HIL/FIT coverage for indications, long values, resource pressure, and deterministic timing sweeps using fixture v2.
- Web: await advertisement cleanup before connecting, bound connection setup by its timeout, and prevent cancelled setup or stale GATT discovery from affecting a later connection.
- Preserve typed BLE error codes when wrapping an existing BLE exception.
2.3.0 #
- Add
isSubscribedandgetSubscribedCharacteristicsto check characteristic notification/indication subscription status in Central mode. - Apple: Accurately report manufacturer-data advertising capabilities.
- Windows: support connectionless manufacturer-data advertising without a GATT service, including state/error reporting and cleanup on stop/disposal.
- Android: add
closeGattOnDetachconnection option to release GATT clients when the app is killed - readRssi commands are not queued anymore
- Android: close the GATT client once the disconnect completes instead of right after
disconnect(), and report the real disconnect status - Android: Fix peripheral
getReadinessState()to check permissions and adapter power before advertising support, and throttlestartAdvertisingBluetooth enable prompts to at most one dialog. - iOS/macOS: complete only the oldest matching pending write on didWriteValueFor
2.2.0 #
- Expose microsecond scan timestamps captured before Flutter event dispatch
- Lower minimum Dart SDK to 3.3 (Flutter 3.19+) to restore compatibility with older stable Flutter releases
- Add
BleCommandQueuesupport toUniversalBlePeripheral(queueType,timeout,clearQueue, andonQueueUpdate) - Add Descriptor Read and Write APIs
- iOS/macOS: Handle CoreBluetooth peripheral transmit queue exhaustion and error handling in
updateCharacteristicValue - Windows: Harden BLE connection lifetime and asynchronous callbacks
- Windows: Harden GATT operation lifetimes, Service Changed handling, and notification subscriptions
- Android: instantly close the GATT client on disconnect
- Android: complete only the oldest matching pending write on onCharacteristicWrite
- iOS/macOS: Handle service discovery failure and timeout to prevent poisoning subsequent
discoverServicescalls
2.1.1 #
- Handle device IDs case-insensitively
- Fix
BleCharacteristicequality andhashCodeto comparepropertiesby value - Android: Fix BluetoothDevice null-safety compile error under Kotlin 2.x
- Android: Make Android write-completion delivery thread-safe
2.1.0 #
- Add optional
queueIdparameter to all APIs - iOS/macOS: add opt-in
AppleConnectionOptionstoconnect(viaConnectionPlatformConfig) — map toCBConnectPeripheralOptionNotifyOnConnectionKey,NotifyOnDisconnectionKeyandNotifyOnNotificationKey, so a suspended app is relaunched into the background to handle connection events (e.g. auto-reconnect while the phone is locked) - Android: add
legacytoAndroidOptions— setlegacy: trueto scan legacy BLE 4.x advertisements (e.g. ESP32) on API 26+; default (null/false) keeps extended-advertisement scanning unchanged from prior releases - Android: add
addServicesInScanResponsetoPeripheralAndroidOptions- setaddServicesInScanResponse: trueto Put advertised service UUIDs in the scan response instead of the primary advertisement - Android: merge manufacturer data with duplicate company id in scan results
2.0.4 #
- iOS: make Bluetooth state restoration optional by enabling it only when the
bluetooth-centralbackground mode is declared - iOS: when state restoration is enabled, init
CBCentralManagerat launch only if Bluetooth permission is granted
2.0.3 #
- iOS/macOS: defer
CBPeripheralManagercreation until peripheral APIs are used, fixing Bluetooth permission prompt on app launch - iOS: add CoreBluetooth state preservation/restoration so the app can be relaunched in the background by a connected peripheral and resume the live connection. Requires the
bluetooth-centralbackground mode inInfo.plist(see README → Permissions → iOS / macOS). - Android: Fix missing scan name after reconnection
- Windows: Fix null pointer crash when BLE device is unpaired during active scan
- Windows: Refactor property value lookups to use a safe lookup function
- Fix Dart primary constructor compatibility
2.0.2 #
- iOS/macOS: retain peripheral from retrievePeripherals to fix API MISUSE on connect
- Android: migrate to built-in Kotlin (removes Kotlin Gradle Plugin usage)
- Use conditional imports for the Linux backend so the package is compatible with the WASM runtime on pub.dev
2.0.1 #
- Add
onConnectionParametersChangeto notify when Android link-layer connection parameters change (API 26+) - Android peripheral: eager Kotlin initialization, thread-safe GATT connection cache, and pairing only via
pair()or when encryption requires it - Android: expose
callbackType,matchMode, andnumOfMatchesonAndroidOptionsso callers can configureScanSettingsto defeat aggressive chip-side advert de-duplication on Pixel devices.callbackTypeaccepts aList<AndroidScanCallbackType>(OR-folded on the native side) and includes a newallMatchesAutoBatchvalue (API 34+).
2.0.0 #
- Add peripheral mode on Android, iOS, macOS, and Windows
- Add
requestConnectionPriorityto allow tuning BLE connection intervals on Android - Add SPM support on Apple
1.2.0 #
- Add
autoConnectparameter toconnect()method for automatic reconnection support on Android and iOS/macOS - Add
serviceDatainBleDevice - Add
AndroidScanModeandreportDelayMillistoAndroidOptionsfor scanning - Add support for BLE scanning from background services (ForegroundTask) on Android.
PermissionHandleris now activity-aware and succeeds silently if permissions are already granted when no activity is available - Add serviceData tracking in Linux advertisements
- Always use custom scan filter on Windows
- Fix Windows crash by handling WinRT exceptions in BLE callback paths
1.1.0 #
- Add readRssi method
1.0.1 #
- Enforce C++20 standard for Windows builds
1.0.0 #
- BREAKING CHANGE:
OnValueChangecallback also includes timestamp - BREAKING CHANGE: Bump minimum IOS version to 13.1
- BREAKING CHANGE: Bump minimum MacOS version to 10.15
- Unified error codes for all platforms
- Add
isScanningapi - Add
hasPermissionsapi - Add
requestPermissionsapi and auto ask permission onstartScan - Add
withDescriptorsparameter indiscoverServicesAPI - Add
timestampinBleDevice - Add
setLogLevelapi for configuring logs disconnectnow waits for disconnection confirmation before returning- Improve Windows disconnection event handling and cleanup
- Fix Windows 11 crash on cancelling pairing
0.21.1 #
- Fix device name resolution on Windows
- Add
exclusionFiltersto filter out devices from scan results
0.21.0 #
- BREAKING CHANGE:
connectionTimeoutargument fromconnect,isPairedandpairAPI renamed totimeout - Add
timeoutargument to all APIs - Add
clearQueue()API
0.20.2 #
- Fix
BleCharacteristic.onValueReceived
0.20.1 #
- Fix
writeWithoutResponse()which was not properly waiting for completion on Android and Apple
0.20.0 #
- BREAKING CHANGE:
bleDevice.isPairedis nowbleDevice.paired - Add new high level API. Services are auto-discovered. the BleDevice class offers convenient member methods and properties.
- Deprecate
readValuein favor ofread - Deprecate
writeValuein favor ofwrite - Deprecate
setNotifiablein favor ofsubscribeNotifications,subscribeIndications,unsubscribe - Fix
getBluetoothAvailabilityStatereporting wrong Bluetooth status on browsers where Web Bluetooth can globally be disabled startScanon web now throws aWebBluetoothGloballyDisabledexception if scanning cannot proceed due to Web Bluetooth being globally disabled- EXAMPLE APP: Migrate to the new high level API
0.19.0 #
- Get and prefer advertised name of scanned devices on Apple
- Cache and return advertised name for system devices on Apple
- Improve Android runtime permissions docs
- Add app showcase in Readme
- EXAMPLE APP: Don't disconnect on leaving the details page
- EXAMPLE APP: Fix Android builds
- EXAMPLE APP: Fix service filter warning on macOS
- EXAMPLE APP: Add types to callbacks
0.18.0 #
- Add Streams:
scanStream,availabilityStream,connectionStream,characteristicValueStream,pairingStateStream - Fix
connectapi bug to detect proper connection state - Fix
getSystemDevices()on Linux - Improve docs for isPaired
0.17.0 #
- Fix Windows crash when calling pair APIs with an unknown deviceId
- Fix Windows crash when calling startScan again after some time
- Fix Windows warning
Unable to establish connection on channelwhen hot restarting - Refactor native Windows code
- Improve Android permission documentation
0.16.0 #
- BREAKING CHANGE:
payloadis nowpayloadPrefix - BREAKING CHANGE:
maskis nowpayloadMask - Bump bluez to 0.8.3
- Do not normalize UUIDs on native side
- Reverse _permissionStatus return values in example app
- Improve readme
- Improve ManufacturerDataFilter
0.15.0 #
getSystemDevices(withServices:)now sets several generic services by default as filtergetConnectionStateon Android will now returnBleConnectionState.disconnectedif device is connected to the system but not to the app- Improve callback error handling
0.14.0 #
- BREAKING CHANGE:
bleDevice.namenow filters out non-printable characters - Add
bleDevice.rawName - Add
disableBluetoothAPI - Bump flutter_web_bluetooth to 1.0.0
- Fix Apple CBCentralManager lazy initialization on
startScan - Fix Android error
scan too frequentlyand auto retry scan once sufficient time has passed - Fix duplicate
onValueChangedevents on Android 11 or earlier - Fix Windows
withServicesfilter - Fix Windows Bluetooth availability state in release builds
- Throw error on Apple if Bluetooth permission is denied on
startScan - Do not throw
Characteristic already notifyingerror. Subscribing to characteristic notifications multiple times is now handled safely
0.13.0 #
- BREAKING CHANGE:
scanFilterfilters are now in OR relation - BREAKING CHANGE:
manufacturerDataHeadis removed fromBleDevice - BREAKING CHANGE:
WebConfigis nowWebOptions - BREAKING CHANGE:
ManufacturerDataFilter.datais nowManufacturerDataFilter.payload - BREAKING CHANGE:
connect()does not return a boolean anymore. It will throw error on connection failure - BREAKING CHANGE:
pair()does not return a boolean anymore. It will throw error on connection failure - BREAKING CHANGE:
onConnectionChangereturns error as well - BREAKING CHANGE: rename in-app pairing capabilities
- Deprecation:
manufacturerDatais deprecated in BleDevice and will be removed in the future - Add
manufacturerDataListasList<ManufacturerData>inBleDevice - Use
ManufacturerDataobject instead ofUint8Listfor manufacturerData - Add
connectionStreamAPI to get connection updates as stream - Auto convert all services passed to
getSystemDevices() - Improve
scanFilterhandling - Return false for receivesAdvertisements on Linux/Web
- Add 1s delay in discoverServices on Linux
0.12.0 #
- BREAKING CHANGE:
unPairis nowunpair - BREAKING CHANGE:
onPairingStateChangedoes not return error anymore - Add
pair(),isPairedandonPairingStateChangesupport for Apple and web connect()andpair()now return a bool result- Add
PlatformConfigproperty inStartScan - Add
WebConfigproperty inPlatformConfig - Fix notifications for characteristics without cccd on Android
- Promote Linux to stable
0.11.1 #
- Trim spaces in UUIDs
- Receive advertisement events on web
- Improve cleanup after disconnection on web
0.11.0 #
- Unify UUID format across all platforms, 128-bit lowercase
- Add BleUuidParser utility methods for UUID parsing
0.10.1 #
- Improve Android error handling
- Improve cleanup after disconnection on Apple and Android
- Improve code level documentation
- Support pairing on Apple
- Fix Android disconnection events sometimes missed
0.10.0 #
- BREAKING CHANGE:
ScanResultis nowBleDevice - BREAKING CHANGE:
getConnectedDevicesis nowgetSystemDevices - BREAKING CHANGE:
isPairedis now nullable - BREAKING CHANGE:
onValueChangedis nowonValueChange - BREAKING CHANGE:
onConnectionChangedis nowonConnectionChange - Add
connectionStateproperty to BleDevice - Add
isSystemDeviceproperty to BleDevice - Add
.perDevicequeue - Support "ProvidePin" pairing on Windows 10/11
- Get RRSI updates on Apple platforms
- Improve enum parsing performance
- Improve code level documentation
0.9.11 #
- Add device name prefix filtering
0.9.10 #
- Fix Windows scan filter
- Remove scan result caching on Windows
- Improve service discovery on Linux
- Use asynchronous callbacks for SetNotifiable
- Remove dependency on
convert - Remove dependency on
collection - Update Android example app Gradle
0.9.9 #
- Improve service discovery on Apple
- Improve reconnection on Apple
- Persist long scan result name on Windows
- Fix Android serviceUuids in scanResults
- Example app improvements
0.9.8 #
- Improve manufacturer data discovery on Windows
- Example app improvements
0.9.7 #
- Fix characteristic keying on linux allowing receiving data from multiple BLE devices at the same time
0.9.6 #
- Fix a Windows issue where characteristics of certain services would not be discovered
- Improve readme
0.9.5 #
- Windows support has graduated from beta to stable
- Support filtering by manufacturer data
- Unify web's optionalServices API with filtering API
- Implement requestMtu in Linux
- Fix wrong manufacturer data in Windows release builds
- Improve logging
0.9.4 #
- Fix Windows crash when no Bluetooth adapter is present
0.9.3 #
- Add scan filter (withServices:) in
startScan() - Add service UUIDs from advertisements in
BleScanResult - Fix Windows release build compilation
0.9.2 #
- Add command queue
- Improve error handling on Android, iOS, macOS, Windows, Linux and web
0.9.1 #
- Improve logging
0.9.0 #
- Improve windows device name discovery
- Improve linux implementation
- Improve titles in example app
0.8.4 #
- Add
WebRequestOptionsBuilder.defaultServicesfor convenience when settingoptionalServiceswhen scanning on web - Add "try online" URL in readme
- Improve readme
- Improve example app
0.8.3 #
- Rename onPairStateChange *> onPairingStateChange
- Improve readme
0.8.2 #
- Improve readme
0.8.1 #
- Update supported platforms
0.8.0 #
- Initial release