Add auto-connect support (#206)
* Add autoConnect support * Enhance autoConnect functionality for Bluetooth devices - Added support for managing a set of auto-connect devices in both Android and iOS implementations. - Updated connection and disconnection logic to handle auto-reconnect scenarios appropriately. - Improved cleanup processes to prevent unwanted reconnections when devices are manually disconnected. * Refactor connection button and add auto-reconnect toggle - Updated the connection button layout for better UI consistency. - Introduced an auto-reconnect toggle to manage automatic reconnections when devices become available. - Enhanced connection and disconnection logic to respect the auto-connect setting. * Update version to 1.2.0 and add CHANGELOG for new features - Bumped version to 1.2.0. - Added CHANGELOG.md detailing new features including support for `autoConnect` and UI updates for automatic reconnection. * Improve readme * Refactor variable naming for clarity in Bluetooth connection logic - Changed variable name from `isAutoConnect` to `shouldAutoConnect` for better readability and understanding of its purpose in the connection state handling. * Refactor connection handling in UniversalBlePlugin - Simplified connection logic by always cleaning up internal state before sending connection change callbacks. - Ensured GATT resources are only closed when autoConnect is disabled, allowing for better management of Bluetooth connections. * Refactor disconnection handling in UniversalBlePlugin - Introduced a new method `handlePeripheralDisconnection` to encapsulate disconnection logic, improving code readability and maintainability. - Updated the `centralManager` methods to utilize the new disconnection handler, ensuring consistent behavior across connection state changes. * Update darwin/Classes/UniversalBlePlugin.swift Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Foti Dim <fotios.dimanidis@a2zebra.de> Co-authored-by: Navideck Labs <130186950+navidecklabs@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -536,7 +536,7 @@ protocol UniversalBlePlatformChannel {
|
||||
func startScan(filter: UniversalScanFilter?) throws
|
||||
func stopScan() throws
|
||||
func isScanning() throws -> Bool
|
||||
func connect(deviceId: String) throws
|
||||
func connect(deviceId: String, autoConnect: Bool?) throws
|
||||
func disconnect(deviceId: String) throws
|
||||
func setNotifiable(deviceId: String, service: String, characteristic: String, bleInputProperty: Int64, completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func discoverServices(deviceId: String, withDescriptors: Bool, completion: @escaping (Result<[UniversalBleService], Error>) -> Void)
|
||||
@@ -681,8 +681,9 @@ class UniversalBlePlatformChannelSetup {
|
||||
connectChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let deviceIdArg = args[0] as! String
|
||||
let autoConnectArg: Bool? = nilOrValue(args[1])
|
||||
do {
|
||||
try api.connect(deviceId: deviceIdArg)
|
||||
try api.connect(deviceId: deviceIdArg, autoConnect: autoConnectArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
|
||||
@@ -42,6 +42,7 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
private var discoverServicesFutures = [DiscoverServicesFuture]()
|
||||
private var rssiReadFutures = [RssiReadFuture]()
|
||||
private var isManageScanning = false
|
||||
private var autoConnectDevices = Set<String>()
|
||||
|
||||
init(callbackChannel: UniversalBleCallbackChannel) {
|
||||
self.callbackChannel = callbackChannel
|
||||
@@ -129,15 +130,41 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
UniversalBleLogger.shared.setLogLevel(logLevel)
|
||||
}
|
||||
|
||||
func connect(deviceId: String) throws {
|
||||
func connect(deviceId: String, autoConnect: Bool?) throws {
|
||||
let peripheral = try deviceId.getPeripheral(manager: manager)
|
||||
peripheral.delegate = self
|
||||
manager.connect(peripheral)
|
||||
let shouldAutoConnect = autoConnect ?? false
|
||||
|
||||
if shouldAutoConnect {
|
||||
autoConnectDevices.insert(deviceId)
|
||||
if #available(iOS 17.0, macOS 14.0, watchOS 10.0, tvOS 17.0, *) {
|
||||
let options: [String: Any] = [CBConnectPeripheralOptionEnableAutoReconnect: true]
|
||||
manager.connect(peripheral, options: options)
|
||||
} else {
|
||||
// Auto-reconnect via CBConnectPeripheralOptionEnableAutoReconnect is only
|
||||
// available on iOS 17.0 / macOS 14.0 / watchOS 10.0 / tvOS 17.0 and later.
|
||||
// On earlier OS versions, enabling `autoConnect` will NOT provide automatic
|
||||
// reconnection behavior. Any desired reconnection must be handled manually
|
||||
// (e.g., in central manager delegate callbacks).
|
||||
UniversalBleLogger.shared.logInfo(
|
||||
"autoConnect requested for device \(deviceId), " +
|
||||
"but automatic reconnection via CBConnectPeripheralOptionEnableAutoReconnect " +
|
||||
"is only available on iOS 17+/macOS 14+/watchOS 10+/tvOS 17+. " +
|
||||
"On this OS version, reconnections must be handled manually."
|
||||
)
|
||||
manager.connect(peripheral)
|
||||
}
|
||||
} else {
|
||||
autoConnectDevices.remove(deviceId)
|
||||
manager.connect(peripheral)
|
||||
}
|
||||
}
|
||||
|
||||
func disconnect(deviceId: String) throws {
|
||||
autoConnectDevices.remove(deviceId)
|
||||
guard let peripheral = deviceId.findPeripheral(manager: manager) else {
|
||||
callbackChannel.onConnectionChanged(deviceId: deviceId, connected: false, error: nil) { _ in }
|
||||
cleanUpConnection(deviceId: deviceId)
|
||||
return
|
||||
}
|
||||
if peripheral.state != CBPeripheralState.disconnected {
|
||||
@@ -445,9 +472,33 @@ private class BleCentralDarwin: NSObject, UniversalBlePlatformChannel, CBCentral
|
||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: true, error: nil) { _ in }
|
||||
}
|
||||
|
||||
public func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error _: Error?) {
|
||||
callbackChannel.onConnectionChanged(deviceId: peripheral.uuid.uuidString, connected: false, error: nil) { _ in }
|
||||
cleanUpConnection(deviceId: peripheral.uuid.uuidString)
|
||||
private func handlePeripheralDisconnection(deviceId: String, error: Error?) {
|
||||
autoConnectDevices.remove(deviceId)
|
||||
callbackChannel.onConnectionChanged(deviceId: deviceId, connected: false, error: error?.localizedDescription) { _ in }
|
||||
cleanUpConnection(deviceId: deviceId)
|
||||
}
|
||||
|
||||
public func centralManager(
|
||||
_: CBCentralManager,
|
||||
didDisconnectPeripheral peripheral: CBPeripheral,
|
||||
timestamp: CFAbsoluteTime,
|
||||
isReconnecting: Bool,
|
||||
error: Error?
|
||||
) {
|
||||
let deviceId = peripheral.uuid.uuidString
|
||||
|
||||
if #available(iOS 17.0, macOS 14.0, watchOS 10.0, tvOS 17.0, *) {
|
||||
if isReconnecting {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
handlePeripheralDisconnection(deviceId: deviceId, error: error)
|
||||
}
|
||||
|
||||
public func centralManager(_: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
|
||||
let deviceId = peripheral.uuid.uuidString
|
||||
handlePeripheralDisconnection(deviceId: deviceId, error: error)
|
||||
}
|
||||
|
||||
public func centralManager(_: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
|
||||
|
||||
Reference in New Issue
Block a user