How to reguraly send data to a BLE peripheral on a IOS (swift) app in background?

Viewed 2508

Im quite new to iOS programming and i'm working with Core Bluetooth in Swift 3 to connect and exchange data to a specific (custom made) ble peripheral.

If the user selects a specific mode in the aplication i need to send data (write characteristic) to the device on a regulary interval (each minute) or on a specific time even if the user opens another app or turn the screen off. If the app is active i can achive this with a scheduledTimer but it stops as soon as the app became inactive. There is any way to continue to send data to the peripheral if the app goes to foreground? Is this possible?

Edit

This is my Background Modes (as described by Deepak Tagadiya): Background Modes

And below some code from my controller:

class MyDevice: UIViewController {

var centralManager: CBCentralManager?
var selectedPeripheral: CBPeripheral?
var mRXCharacteristic: CBCharacteristic?
var mTXCharacteristic: CBCharacteristic?
var auto_timer = Timer()


@IBOutlet weak var AutoSwitch: UISwitch!
@IBAction func AutoSwitch(_ sender: UISwitch) {
        if(sender.isOn == true){
            activateAutoModeTask()
        } else {
           disableAutoModeTask()
        }

}

override func viewDidLoad() {
    super.viewDidLoad()

    centralManager = CBCentralManager(delegate: self, queue: nil)   
    (…)
}

func activateAutoModeTask(){


    auto_timer.invalidate() // just in case this button is tapped multiple times

    // start the timer
    auto_timer = Timer.scheduledTimer(timeInterval: 20, target: self, selector: #selector(updateTask), userInfo: nil, repeats: true)

}

func disableAutoModeTask(){
    auto_timer.invalidate()
}

func updateTask(){
    let new_value = getNewValue() //function that get the new value


    send(text: new_value)
}

func send(text aText : String) {
    (…)
    self.selectedPeripheral?.writeValue(data, for: self.mRXCharacteristic!, type: .withResponse)
}

}

extension MyDevice: CBCentralManagerDelegate {

func centralManagerDidUpdateState(_ central: CBCentralManager) {
    (…) 
}

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    (…)
    peripheral.delegate = self
    selectedPeripheral = peripheral
}

}

extension MyDevice: CBPeripheralDelegate {

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
    (...)
}


func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    (…)
}

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    (…)
}

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    (…)

    responseReceived(response: response_text)
}

}

So i'm able to write to the peripheral if the app is active but not when the app goes to background (if i click on Home button for example). Maybe something is still missing...

Thanks in advance!

3 Answers

I was also facing the same issue and resolved it by doing this. Enable Background mode features according to your requirements from capabilities.

enter image description here

Hope this will help you.

Follow below steps:

  1. Open project.
  2. Select Target(Below the Project).
  3. Go To ‘Capabilities’ Tab.
  4. Select ‘Background Modes’.(By default it is off)
  5. Select ‘Uses Bluetooth LE accessories’ and ‘Act as a Bluetooth LE accessory’(Both).
  6. Run Project. enter image description here
Related