I'm struggling with the problem which is, I can not reestablish the connection with my BLE Device when user force quits the app. My app works like this:
- First launch the app user should connect with the BLE Device - that works
- When app is in background the connections is still working
- If I turn off the BLE Device and turn on again the connection is reestablished - works
- When user goes out and turn back home the connection is reestablished and user gets notification that he is close to the Device - works
All of this is solved by turning Bluetooth 4.0 LE into iBeacon. When user is close enough an iBeacon starts sending signals and iOS app is triggered and user gets push notification an connection is reestablished.
The problem appears when user force quits the app. iBeacon still works because when user is connected to BLE the BLE device works as.. Bluetooth device, but when the connection is lost BLE works as iBeacon and advertise the iOS app. When user force quits the app the user gets local push notification that app is close to iBeacon so it means the app is relaunch for the couple of seconds (10s I think) but I can not with this reestablish connection.
This is the code for tigger the notification and as I hoped for BLE reconnection after fore quit.
func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
// Check if the user's INSIDE the region, not outside...
guard state == CLRegionState.inside else { print("Error"); return }
if state == CLRegionState.inside{
let content = UNMutableNotificationContent()
content.title = "Device found!"
content.body = "You're close to your BLE Device, reestablish connection!"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let request = UNNotificationRequest(identifier: "1389402823904", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { (err:Error?) in
}
centralManager.scanForPeripherals(withServices: nil, options: nil)
let uuid = UUID(uuidString: "74278BDA-B644-4520-8F0C-720EAF059935")!
guard let mainPeripheral = mainPeripheral else {return}
centralManager.connect(mainPeripheral, options: nil)
centralManager.retrievePeripherals(withIdentifiers: [uuid])
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
self.centralManager.stopScan()
}
}
}
}
For the simplicity the uuid is hardcoded.
As I understand the didDeterminateState
is triggered when iBeacon sends signal and I am checking the CLRegionState
if the region is inside which means close to the iBeacon the method for local notifications gets triggers, then I need to rescan for BLE devices so I am calling scanForPeripherals
but not the connect
method. ScanForPeripherals
should call the didDiscover
method:
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
print(peripheral)
if peripheral.name == "DOPEY"{
peripheral.delegate = self
peripheral.discoverServices([HM_10_ServiceCharacteristic])
mainPeripheral = peripheral
centralManager.connect(peripheral, options: nil)
centralManager.stopScan()
}
}
When it founds DOPEY
peripheral name the device should connect.
For tests I am using HM-10 Bluetooth 4.0 LE.
When user force quits the app it sends local push notification but does not reestablish the connection.
I am looking forward for any kind of help. Appreciate!