Reputation: 41
Im trying to create an application which connects to a BP cuff. I want to enable state restoration in the app so that even if the app is killed by the system the app can still be invoked when the BP cuff is available and transmitting. Here are some of the things I have tried so far.
1) Adding a resource identifier to centralManager init and assigning a background serial queue to it
var ble_dispatchQueue = DispatchQueue(label: "com.xyz.ios.ble")
let opts = [CBCentralManagerOptionShowPowerAlertKey : true, CBCentralManagerOptionRestoreIdentifierKey:
"ios.xyz.ble.peripheral.identifier"] as [String : Any]
self.centralManager = CBCentralManager(delegate : self, queue : ble_dispatchQueue, options : opts)
2) implementing willRestoreState and centralManagerDidUpdateState
func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {
print("will restore state called")
if let peripheralsObject = dict[CBCentralManagerRestoredStatePeripheralsKey] {
// 2
let peripherals = peripheralsObject as! Array<CBPeripheral>
// 3
if peripherals.count > 0 {
// 4
self.peripheralDevice = peripherals[0]
// 5
self.peripheralDevice?.delegate = self
}
}
}
centralManagerDidUpdateState :
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state != .poweredOn {
self.peripheralDevice = nil
return
}
startScan()
// 1
guard let peripheral = self.peripheralDevice else {
return
}
// 2
guard peripheral.state == .connected else {
return
}
// 3
guard let peripheralServices = peripheral.services else {
return
}
// 4
serviceUUID = deviceParameters.deviceTypeUUIDs![0]
if let serviceIndex = peripheralServices.index(where: {$0.uuid == serviceUUID}) {
let ANDService = peripheralServices[serviceIndex]
let characteristicUUIDs = deviceParameters.deviceCharacteristicUUIDs
if let cUUIDs = characteristicUUIDs, let characteristics = ANDService.characteristics {
// 6
for i in 0..<cUUIDs.count {
if let characteristicIndex = characteristics.index(where : {$0.uuid == cUUIDs[i]}) {
let characteristic = characteristics[characteristicIndex]
// 7
if !characteristic.isNotifying {
peripheral.setNotifyValue(true, for: characteristic)
} else {
peripheral.readValue(for: characteristic)
}
} else {
// 8
peripheral.discoverCharacteristics(characteristicUUIDs, for: ANDService)
}
}
}
} else {
// 5
peripheral.discoverServices([serviceUUID])
}
}
The way Im trying to test it is by calling :-
kill(getpid(), SIGKILL);
to simulate process killing by the system. I'm not fiddling with bluetooth state / airplane mode or phone reboot. Im initializing my centralManager inside didLaunchWithOptions I have breakpoints at didLaunchWithOptions which gets called everytime the BP cuff is ready to connect and at willRestoreState which never gets called.
Can someone please suggest what else I can do to invoke willRestoreState?
Upvotes: 2
Views: 1936
Reputation: 3347
You need to add a restoration id to your CBCentralManager
or the delegate method is never called.
let options = [CBCentralManagerOptionRestoreIdentifierKey: "my-central"]
self.centralManager = CBCentralManager(delegate: self, queue: nil, options: options)
Once you've done that willRestoreState
is always called when the CBCentralManager
is instantiated.
Also, make sure you have UIBackgroundModes
(Array) with 'bluetooth-central' as an item in your Info.plist.
Upvotes: 4