feat(darwin): notify central of background connection events - #264
Conversation
Set CBConnectPeripheralOptionNotifyOnConnection/Disconnection/Notification on connect() so CoreBluetooth surfaces connection, disconnection and notification events that occur while the app is suspended (relaunching it into the background to handle them). This keeps a backgrounded central — e.g. a fitness app reconnecting to a previously paired trainer — responsive without the user having to foreground the app. Consolidated to a single manager.connect(options:) call; the iOS 17+ auto-reconnect option is merged into the same dictionary, so behavior on that path is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request modifies the Swift connection logic in UniversalBlePlugin to unconditionally enable background connection options (CBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey, and CBConnectPeripheralOptionNotifyOnNotificationKey) when connecting to a peripheral. Feedback indicates that enabling these options by default can trigger intrusive system alerts when the app is suspended, and recommends making them configurable or opt-in instead.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| var options: [String: Any] = [ | ||
| CBConnectPeripheralOptionNotifyOnConnectionKey: true, | ||
| CBConnectPeripheralOptionNotifyOnDisconnectionKey: true, | ||
| CBConnectPeripheralOptionNotifyOnNotificationKey: true, | ||
| ] |
There was a problem hiding this comment.
Enabling CBConnectPeripheralOptionNotifyOnConnectionKey, CBConnectPeripheralOptionNotifyOnDisconnectionKey, and CBConnectPeripheralOptionNotifyOnNotificationKey unconditionally will cause iOS to display system alerts (popups/notifications) to the user whenever these events occur while the app is suspended. This is an intrusive behavior change for existing users of the library who do not expect or want these alerts.\n\nThese options should be opt-in and configurable (e.g., via platform-specific connection options passed from the Dart layer) rather than enabled by default.
var options: [String: Any] = [:]|
@jonasbark Thank you for the PR and suggestions, Yes i think this should be an Opt-in connect option, and like you mentioned, we should add ios specific options in connect api |
Address review feedback on Navideck#264: instead of unconditionally passing the CBConnectPeripheralOptionNotifyOn*Key options on Apple platforms, expose them as an opt-in AppleConnectionOptions carried by a new ConnectionPlatformConfig parameter on connect(), mirroring the existing PeripheralPlatformConfig pattern. Default behavior is unchanged. Threads the new parameter through the pigeon definition (regenerated for Dart/Kotlin/Swift/C++), the platform interface, and all platform implementations; only iOS/macOS act on it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Done in 9b9ac03 — the notify options are now opt-in and off by default.
Also updated the README (new "Background connection events (iOS/macOS)" section) and CHANGELOG, and marked the PR ready for review. Happy to adjust naming/shape if you'd prefer something different. |
There was a problem hiding this comment.
Pull request overview
Adds an opt-in, Apple-specific connection configuration so CoreBluetooth can surface connection/disconnection/notification events while an app is suspended (via relaunch into the background), threaded end-to-end through the Dart API and regenerated Pigeon bindings for all supported platforms.
Changes:
- Add
ConnectionPlatformConfig/AppleConnectionOptionsand pass it throughUniversalBle.connect()(andBleDevice.connect) into the Pigeonconnectcall. - Implement Darwin support by mapping the options to
CBConnectPeripheralOptionNotifyOn*Keyand consolidating connect option handling into a singlemanager.connect(..., options:)call. - Regenerate Pigeon outputs across Dart/Kotlin/Swift/C++ and plumb the new argument through non-Apple platforms as accepted-but-ignored, plus update docs/changelog.
Reviewed changes
Copilot reviewed 19 out of 21 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| windows/src/universal_ble_plugin.h | Updates Windows channel interface Connect signature to accept platform_config. |
| windows/src/universal_ble_plugin.cpp | Accepts platform_config in Windows connect implementation (ignored on Windows). |
| windows/src/generated/universal_ble.g.h | Adds generated C++ Pigeon types for AppleConnectionOptions and ConnectionPlatformConfig and updates connect API signature. |
| windows/src/generated/universal_ble.g.cpp | Implements new generated C++ Pigeon types and updates codec/type IDs + connect message decoding. |
| test/universal_ble_test_mock.dart | Updates test mock platform interface to include platformConfig in connect. |
| README.md | Documents iOS/macOS background connection event options and sample usage. |
| pigeon/universal_ble.dart | Adds new Pigeon model types and extends connect API with platformConfig. |
| lib/universal_ble.dart | Exports the newly generated connection config types from the public library surface. |
| lib/src/universal_ble.g.dart | Regenerated Dart Pigeon output with new types and updated connect message encoding. |
| lib/src/universal_ble.dart | Adds platformConfig to UniversalBle.connect and forwards it into the platform implementation. |
| lib/src/universal_ble_web/universal_ble_web.dart | Accepts (and ignores) platformConfig for web implementation. |
| lib/src/universal_ble_pigeon/universal_ble_pigeon_channel.dart | Forwards platformConfig through the Pigeon channel connect call. |
| lib/src/universal_ble_linux/universal_ble_linux.dart | Accepts (and ignores) platformConfig for Linux implementation. |
| lib/src/interfaces/universal_ble_platform_interface.dart | Extends platform interface connect signature with platformConfig. |
| lib/src/extensions/ble_device_extension.dart | Extends BleDevice.connect to accept and forward platformConfig. |
| example/lib/data/mock_universal_ble.dart | Updates example mock to match the new connect signature. |
| darwin/universal_ble/Sources/universal_ble/UniversalBlePlugin.swift | Implements Darwin connect option dictionary construction and maps AppleConnectionOptions to CoreBluetooth connect options. |
| darwin/universal_ble/Sources/universal_ble/UniversalBle.g.swift | Regenerated Swift Pigeon output including new types and updated connect signature/codec. |
| android/src/main/kotlin/com/navideck/universal_ble/UniversalBlePlugin.kt | Updates Android connect signature to accept platformConfig (ignored on Android). |
| android/src/main/kotlin/com/navideck/universal_ble/UniversalBle.g.kt | Regenerated Kotlin Pigeon output including new types and updated connect signature/codec. |
| CHANGELOG.md | Notes the new opt-in iOS/macOS connection options feature in the release notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -1,5 +1,6 @@ | |||
| ## 2.1.0 | |||
| * Add optional `queueId` parameter to all APIs | |||
| * iOS/macOS: add opt-in `AppleConnectionOptions` to `connect` (via `ConnectionPlatformConfig`) — map to `CBConnectPeripheralOptionNotifyOnConnectionKey`, `NotifyOnDisconnectionKey` and `NotifyOnNotificationKey`, so a suspended app is relaunched into the background to handle connection events (e.g. auto-reconnect while the phone is locked) | |||
Summary
Add an opt-in way to have CoreBluetooth surface connection / disconnection / characteristic-notification events that occur while the app is suspended, relaunching the app into the background to handle them.
connect()gains an optionalplatformConfigparameter carrying Apple-specific options (mirroring the existingPeripheralPlatformConfigpattern):All flags default to
false, so behavior is unchanged for existing consumers (these keys can show a system alert to the user while the app is suspended, andnotifyOnNotificationfires per characteristic notification — hence opt-in, per review feedback).The new parameter is threaded through the pigeon
connectsignature (regenerated for Dart/Kotlin/Swift/C++) and all platform implementations; only iOS/macOS act on it, other platforms accept and ignore it. The Darwin change also consolidates the three previousmanager.connect(...)call sites into a singleconnect(peripheral, options:); the existing iOS 17+CBConnectPeripheralOptionEnableAutoReconnectis merged into the same dictionary, so that path is behaviorally unchanged.Motivation
I maintain a fitness app (BikeControl) that stays connected to a smart trainer/sensors for the duration of a workout. Users routinely background the app (lock the phone, switch to music, etc.). Combined with the
bluetooth-centralbackground mode and the CoreBluetooth state restoration that already landed in 2.0/2.1, these options let the central keep reacting to peripheral events — most importantly reconnecting to a previously paired peripheral — while suspended, instead of going silent until the user foregrounds the app.I've been carrying this as a one-line fork of
universal_blefor a while. Everything else in that fork has since landed upstream — this is the only patch left, so I'd love to upstream it and retire the fork.Testing
flutter analyzeandflutter testpass (81/81).🤖 Generated with Claude Code