0
votes

I'm simultaneously advertising a BLE peripheral and a beacon combined in one NSDictionary and advertised by the same CBPeripheralManager. In the same app I'm scanning for BLE peripherals and monitoring the beacon.

It doesn't work - Simultaneously advertising the peripheral and the beacon seems to cause a strange conflict. In foreground the beacon will be detected (region entry) but the callbacks for the CBPeripheral don't fire. When device A backgrounds the app, the peripheral callbacks get triggered on the app running on device B and service and characteristic query runs as expected.

The behaviour suggests that the advert for the beacon blocks the advert for the peripheral when in foreground, but the peripheral advert is effective when the app is in the background.

The advertising code is as follows:

    NSDictionary *adUUIDs = [[NSDictionary alloc] initWithObjectsAndKeys:@"CNT100A", @"kCBAdvDataLocalName", _serviceUUIDs, @"kCBAdvDataServiceUUIDs", nil];

    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"328204DB-5128-40B4-9C73-65DF66899945"];
    CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:1 minor:1 identifier:@"com.aurl.id"];
    NSDictionary *beaconData = [beaconRegion peripheralDataWithMeasuredPower:nil];

    NSMutableDictionary *advert = [NSMutableDictionary dictionaryWithDictionary:beaconData];
    [advert addEntriesFromDictionary:adUUIDs];

    [_adManager startAdvertising:advert];

Which produces this:

(lldb) po advert
{
    kCBAdvDataAppleBeaconKey = <328204db 512840b4 9c7365df 66899945 00010001 c8>;
    kCBAdvDataLocalName = CNT100A;
    kCBAdvDataServiceUUIDs =     (
        "5351CAD0-B1CE-4E38-8673-76D05124E915",
        "E7A48922-5D43-4237-821D-D710E69EE1CD"
    );
}

If I remove either the peripheral or the beacon advertisement item from the dictionary before calling startAdvertising, the app behaves normally.

My CBCentralManager scan is called as follows:

[_searchManager scanForPeripheralsWithServices:serviceUUIDs options:@{CBCentralManagerScanOptionSolicitedServiceUUIDsKey: serviceUUIDs, CBCentralManagerScanOptionAllowDuplicatesKey:continuousSearch}];

And my region monitoring is standard:

    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"328204DB-5128-40B4-9C73-65DF66899945"];
    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:1 minor:1 identifier:@"com.aurl.id"];
    self.beaconRegion.notifyEntryStateOnDisplay = YES;

    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;

    [self.locationManager requestAlwaysAuthorization];
    [self.locationManager startMonitoringForRegion:self.beaconRegion];

I've been trying to get this to work for longer than I care to admit... Have I misunderstood something simple? Does Apple restrict some functionality in this area?

1
An iOS app can't act as a beacon in the background, which is possibly why you are seeing the peripheral act correctly in the background. Why do you want to be a beacon and a peripheral? A peripheral should be sufficient, particularly if you are advertising and connecting in the backgroundPaulw11
I would like to exploit the iOS beacon functionality that allows the app to get a callback even it's not running (just installed) when entering a region. In this case the region would be the proximity to a copy of the app running on another device (in foreground).TinoK
If you know the UUID of the service you are looking for (which you will since it is your service) then you can scan for those peripherals in the background. And more importantly your app can advertise that service in the background. Using a beacon the advertising app will need to be in the foreground with the phone unlocked.Paulw11
Sure - I have the central/peripheral working in foreground and background. I just wanted to extend the functionally a bit so that I could take some action on a device that is not even running the app when it is in close proximity to a device which has it in the foreground. As mentioned, the issues appears to be simultaneous advertising of beacon and peripheral in the foreground.TinoK
But if you use Bluetooth state restoration you can get notified of peripheral discovery when the app isn't runningPaulw11

1 Answers

0
votes

Unfortunately, it appears from your description that you cannot advertise an iBeacon and another peripheral service simultaneously iOS.

This is not super surprising. Beacons advertise at 10 Hz, and while most Bluetooth chips allow more frequent transmission, they typically do not support interleaving at a chip level. This means that if iOS wanted to support broadcasting both advertisement types at the same time on all chips (all iPhone and iPad models), it would have to include special code to make the chip do so. It sounds like me it does not.

To be clear, I have no special information on the internal implementation of broadcasting multiple advertising types simultaneously on iOS. But I do know from experience that doing what you want requires jumping through special hoops at a low-level, so it is very likely that iOS simply does not allow it.