4

I am Working on BLE project, everything works fine when the app in the foreground.It can discover and connect to the peripheral, all the call back method work perfectly.

But the problem is that, when the app in the background mode (I press home button). Only the centralManagerDidUpdateState delegate method get called.

- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
        case CBCentralManagerStatePoweredOn:
          [self.cbCentralManager scanForPeripheralsWithServices:nil options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
            break;
        default:
            break;
    }
}

I use scanForPeripheralsWithServices:nil option, But when the app in the background, the didDiscoverPeripheral call back never called. I have edit my plist file with "bluetooth-central" option to support ble central role in background.

Any idea why didDiscoverPeripheral method not call when app in the background?

ding
  • 248
  • 4
  • 13
  • `didConnwctPeripheral` will get called in response to a `connect`, not a `scanForPeripheralsWithServices` . Do you get a call to `didDiscoverPeripheral`? Note that the duplicates option is ignored in the background and you will only get a single discovery event for each peripheral. – Paulw11 Aug 21 '15 at 21:08
  • 1
    Yeah, the problem is the `didDiscoverPeripheral` not called actually, I have edited my question. If the app in the foreground already start scanning the peripherals, When the app in the background, does the `scanForPeripheralsWithServices` call back get called for the same peripheral? Does iOS ignore the duplicates when it found the peripheral in the foreground? – ding Aug 22 '15 at 08:03
  • 1
    Correct, if a discovery notification for a given peripheral has already been delivered in the foreground or the background you will not receive any further discovery notifications for that peripheral in the background. – Paulw11 Aug 22 '15 at 08:05
  • 1
    If I would like still receive `didDiscoverPeripheral` call back for the same peripheral in the background what should I do? Do I initial a new Central class to restart scanning? I actually want to reconnect the same peripheral when the app in the background. If the `didDiscoverPeripheral` not called how could I reconnect. In the apple Bluetooth guide, I could use the `retrievePeripheralsWithIdentifiers:` to restore the peripheral. But I get null peripheral from the `retrievePeripheralsWithIdentifiers:` method. – ding Aug 22 '15 at 08:11
  • 1
    If you want to connect, simply issue a connect. Once the peripheral comes back into range the connection will complete and you will get a call to `didConnectPeripheral`. Basically in `didDisconnectPeripheral` simply call connect with their peripheral object – Paulw11 Aug 22 '15 at 08:48

4 Answers4

3

I was working on Estimote Nearable type beacons. After iOS10 SDK update, I encountered exception from CBCentralManager stating :

<CBCentralManager: 0x17009e050> has provided a restore identifier but the delegate doesn't implement the centralManager:willRestoreState: method

To fix this, Turn-On "Background Mode", in Xcode -> Capabilities -> Background Mode

enter image description here

byJeevan
  • 3,240
  • 2
  • 33
  • 54
2

Scan for nil( scanForPeripheralsWithServices:nil) services will not work in background. You must search for some specific service in background.

You have to set the UUID in scanForPeripheralsWithServices: method which Peripherals/BLE device is advertising.

Ameet Dhas
  • 2,400
  • 4
  • 22
  • 38
2

Paulw11 said are right, If your app find the peripherals in the foreground. It will not call the didDiscoverPeripheral for the same peripherals when it enters the background.

For more information about the iOS BLE Behavior in the background mode. You can check this answer What exactly can CoreBluetooth applications do whilst in the background?

Community
  • 1
  • 1
caviar
  • 98
  • 7
1

From Official Apple reference

You can provide an array of CBUUID objects—representing service UUIDs—in the serviceUUIDs parameter. When you do, the central manager returns only peripherals that advertise the services you specify (recommended). If the serviceUUIDs parameter is nil, all discovered peripherals are returned regardless of their supported services (not recommended). If the central manager is already scanning with different parameters, the provided parameters replace them. When the central manager object discovers a peripheral, it calls the centralManager:didDiscoverPeripheral:advertisementData:RSSI: method of its delegate object.

Apps that have specified the bluetooth-central background mode are allowed to scan while in the background. That said, they must explicitly scan for one or more services by specifying them in the serviceUUIDs parameter. The CBCentralManagerOptionShowPowerAlertKey scan option is ignored while scanning in the background.

Here

Apps that have specified the bluetooth-central background mode are allowed to scan while in the background. That said, they must explicitly scan for one or more services by specifying them in the serviceUUIDs parameter.

So scanForPeripheralsWithServices:nil with nil it will not work in background , you need to specify list of UUIDS

Mihir Mehta
  • 13,424
  • 2
  • 59
  • 85