2

I'm creating an iOS app that triggers a server call whenever you come into bluetooth proximity of another iPhone running the app. Each iOS device should have some unique bluetooth advertisement identifier (e.g major/minor combo) so the appropriate server/DB call can be made.

My first plan was to use the standard iBeacon API (CoreBluetooth + CoreLocation). Worked like a charm but hit a standstill when I realized that you can't advertise bluetooth while your app in background using this method.

Method 1

//Create the NSUUID Object
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"6CA7D72E-824E-45D1-99E9-02BD33599A81"];

//Initialize the Beacon Region
self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:1 minor:1 identifier:@"com.emjoseph.test"];

//Get the beacon data to advertise
self.myBeaconData = [self.myBeaconRegion peripheralDataWithMeasuredPower:nil];

//Start the peripheral manager
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];

-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{    
if(peripheral.state == CBPeripheralManagerStatePoweredOn){
    //Bluetooth is on - start broadcasting
    [self.peripheralManager startAdvertising:self.myBeaconData];        
} 

}

My second attempt was using the Instrument/Vicinity API set up by Bentford on Github that replicates the iBeacon API solely using CoreBluetooth. This solved the issue of being able to advertise in the background. The problem though was that I couldn't figure out how to send the equivalent of a major or minor in the bluetooth advertisement data and this is limiting because the receiving phone needs to some unique identifier of the device it received data from so it can make the appropriate server/DB call. It seems I just have access to a UUID and name property in the advertisement data.

Method 2

NSDictionary *advertisingData = @{CBAdvertisementDataLocalNameKey:@"emjoseph",
                                  CBAdvertisementDataServiceUUIDsKey:@[CBUUID],
                                   };

// Start advertising over BLE
[peripheralManager startAdvertising:advertisingData];

Any hunches on how I can I achieve the desired setup? I thought about using method 2's CBAdvertisementDataLocalNameKey property string as a unique ID, but it has its limits.

Also I'd like all users of the app to be on the same UUID to filter out unwanted signals.


To reiterate once more, the basic flow of the app is: When person A gets close to person B's phone, person A receives some unique ID from person B via bluetooth (e.g major/minor combo) and person A uses that unique ID to retrieve the relevant information from the DB/server. The only stipulation is that I'd like for this process to happen when the app is running in the background as well.

Eugene
  • 1,377
  • 2
  • 18
  • 22
  • you can not advertise when app is in background. even if you could it would be for fraction of second not all time. my advice would be use iBeacon for broadcasting presence of location. – Sheshnath Nov 13 '14 at 07:04
  • 1
    You probably need to enhance the code so that it advertises a Bluetooth peripheral service with a characteristic. Then when you detect the other device you can connect to it and read the value of the characteristic, which could be the vendor identifier or some other id that you have registered on your server – Paulw11 Nov 13 '14 at 07:10
  • From my findings it seems Apple is intentionally limiting this background peer-to-peer device communication capability. For the pure Core Bluetooth solution, the peripheral can advertise in background, but central won't scan when screen is locked. For the iBeacon solution, it seems the central can always be waken even it's not running in background, but the peripheral has to be in foreground to broadcast (unless it's a hardware iBeacon). But I'd like to know if there does exist solution to your question. – Yuan XU Nov 14 '14 at 07:04
  • I hope you find / figure out an answer to this! I'm trying to find a way to broadcast from the background of one device (using CoreBluetooth) and have it detected on another device (also in the background) as an iBeacon *by* CoreLocation (so that I can use background server-calls). I'm using Vicinity, but A) it doesn't seem that CoreLocation will react, and B) I also need the major/minor values. I have little clue about this, but might replicating the iBeacon profile do the trick? http://stackoverflow.com/questions/18906988/what-is-the-ibeacon-bluetooth-profile/20932265#20932265 – Dan Nov 29 '14 at 17:10

0 Answers0