Swift - BLE app reconnects / scans after suspended

I am currently writing an application that connects via BLE to an external device. All operations are fine when the application is in the foreground ..... including connecting, receiving data, and reconnecting (in case the device is out of range) via the reconnect protocol I wrote. The app also functions correctly when given, but the BLE connection stays alive.

However, the only instance where the application fails is if the application is encrypted and then the BLE device is out of range. Once the connection is broken, the app seems to be paused by iOS after a few seconds and none of the code I've written will continue to function ... even if I put the device back in range. The only way to restore functionality is to bring the application back to the foreground again. (Note: I have info.plist file and all other settings configured accordingly for background.serviceManager functions)

I've read some documentation and it looks like it boils down to the save / restore code not being implemented correctly. I went ahead and implemented the "willRestoreState" and "didUpdateState" commands, but the app still won't connect to the device after being suspended in the background.

I've shown some relevant codes below, including the willRestoreState, didUpdateState and didDisconnect methods. Any ideas or suggestions? Thank!

//define service+characteristic UUIDS
let serviceUUID                          = CBUUID(string: "xxxxxxxxx")
let streamingCharacteristicUUID          = CBUUID(string: "xxxxxxxxx")

//Local dictionary of UUIDs for connected devices (the ble code updates this var with each connected device)
var devicesUniqueId:[UUID:String] = [UUID:String]()

//Local dictionary of connected peripherals, with respect to each of their UUIDS (the ble code updates this var with each connected device)
var sensorPeripheral = [UUID:CBPeripheral]()



///restoreState function
 func centralManager(_ central: CBCentralManager, willRestoreState dict: [String : Any]) {

    if let peripheralsObject = dict[CBCentralManagerRestoredStatePeripheralsKey] {

        let peripherals = peripheralsObject as! Array<CBPeripheral>       
        print ("starting restorestate code")
        if peripherals.count > 0 {
            for i in 0 ..< peripherals.count {
                print ("starting restorecheck")

//Check if the peripheral exists within our list of connected peripherals, and assign delegate if it does
                if self.devicesUniqueId.keys.contains(peripherals[i].identifier) {
                    peripherals[i].delegate = self
                }
            }
        }
    }
}



 func centralManagerDidUpdateState(_ central: CBCentralManager)
{ 
    if central.state != .poweredOn
    {
        return
    }
     self.startScanning()

    //////Preservation + Restoration code////////


//Iterate through array of connected UUIDS
    let keysArray = Array(self.patchDevicesUniqueId.keys)
        for i in 0..<keysArray.count {

//Check if peripheral exists for given UUID
           if let peripheral = self.sensorPeripheral[keysArray[i]] {              
            print("peripheral exists")       

//Check if services exist within the peripheral
            if let services = peripheral.services {           
                 print("services exist")   

//Check if predefined serviceUUID exists within services 
                if let serviceIndex = services.index(where: {$0.uuid == serviceUUID}) {                 
                     print("serviceUUID exists within services")          
                    let transferService = services[serviceIndex]
                    let characteristicUUID = streamingCharacteristicUUID        

//Check if predefined characteristicUUID exists within serviceUUID
                    if let characteristics = transferService.characteristics {                    
                         print("characteristics exist within serviceUUID")                           

                        if let characteristicIndex = characteristics.index(where: {$0.uuid == characteristicUUID}) {                               
                             print("characteristcUUID exists within serviceUUID")                      
                            let characteristic = characteristics[characteristicIndex]  

//If characteristicUUID exists, begin getting notifications from it
                            if !characteristic.isNotifying {                                   
                                 print("subscribe if not notifying already")
                                peripheral.setNotifyValue(true, for: characteristic)
                            }
                            else {                                    
                                 print("invoke discover characteristics")    
                            peripheral.discoverCharacteristics([characteristicUUID], for: transferService)
                            }                               
                        }                                                        
                    }                        
                }
                else {
                    print("invoke discover characteristics")
                    peripheral.discoverServices([serviceUUID])
                }                 
            }            
        }
    }
}



//didDisconnect method to handle a connect command issue
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?)
{


//commented out unnecessary code

    self.removePeripheralData(peripheral: peripheral)

    if(sensorCount>0){
        sensorCount -= 1
    }

}


//removePeripheralData function used in didDisconnect
 func removePeripheralData ( peripheral: CBPeripheral) {

   //Commented out unnecessary code

            //Issue reconnect command
            print ("issuing reconnect command")
              centralManager.connect(peripheral, options: nil)

     //Commented out unnecessary code

    handleDidRemoveDevice()
}

      

+3


source to share





All Articles