Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
255 views
in Technique[技术] by (71.8m points)

iphone - iOS CoreBluetooth / iBeacon: Advertise an iBeacon and a peripheral service concurrently

I'm writing an application for iOS that requires that the application advertise both an iOS iBeacon as well as advertise peripheral service concurrently. It's necessary that the service is advertised rather that simply discoverable on the peripheral because the use case requires the central (in BLE parlance) connect to the peripheral after being woken up by iOS (but still in the background) due to proximity to the iBeacon. Apps running in the background on centrals can only discover peripheral by available service rather than discovering all peripherals [] ; My code works to advertise either the service or the iBeacon but I haven't figured out how to do both at the same time. It's possible that the iBeacon uses 21bytes of the 38bytes of available space and there simply isn't enough space to advertise a beacon as well as a service?

This works (beacon):

self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid 
    major:1 
    minor:1 
    identifier:@"bentboolean"];
NSMutableDictionary *dict = [[self.beaconRegion peripheralDataWithMeasuredPower:nil] mutableCopy];    
[self.peripheralManager startAdvertising:dict ];

This works (service):

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:@[serviceUUID] forKey:CBAdvertisementDataServiceUUIDsKey];
[self.peripheralManager startAdvertising:dict ];

Adding the two together, trying to advertise both services at the same time doesn't work. It only advertises the Beacon, not the service:

self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid 
    major:1 
    minor:1 
    identifier:@"bentboolean"];
NSMutableDictionary *dict = [[self.beaconRegion peripheralDataWithMeasuredPower:nil] mutableCopy];  
[dict setValue:@[serviceUUID] forKey:CBAdvertisementDataServiceUUIDsKey];  
[self.peripheralManager startAdvertising:dict ];

Thanks for taking a look!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I was able to get this going with a separate CLLocationManager and CLBeaconRegion for both the reciever and the beacon separately:

#import "GRBothViewController.h"

@interface GRBothViewController ()

@end

@implementation GRBothViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];


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

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

    [self initBeacon];
    [self initRegion];
    [self locationManager:self.locationManager didStartMonitoringForRegion:self.scannerRegion];
}

- (void)initBeacon {
    NSLog(@"Starting beacon");

    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString: @"23542266-18D1-4FE4-B4A1-23F8195B9D39"];
    self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
                                                                major:1
                                                                minor:1
                                                           identifier:@"com.thisisgrow.Grow"];
    [self transmitBeacon:self];
}

- (IBAction)transmitBeacon:(id)sender {
    self.beaconPeripheralData = [self.beaconRegion peripheralDataWithMeasuredPower:nil];
    self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self
                                                                     queue:nil
                                                                   options:nil];
}

-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
    if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
        NSLog(@"Powered On");
        [self.peripheralManager startAdvertising:self.beaconPeripheralData];
    } else if (peripheral.state == CBPeripheralManagerStatePoweredOff) {
        NSLog(@"Powered Off");
        [self.peripheralManager stopAdvertising];
    }
}

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
    [self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}

- (void)initRegion {
    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"23542266-18D1-4FE4-B4A1-23F8195B9D39"];
    _scannerRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@"com.thisisgrow.Grow"];
    _scannerRegion.notifyEntryStateOnDisplay = YES;
    [_locationScanner startMonitoringForRegion:self.scannerRegion];
}

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
    //SCANNER
    [self.locationScanner startRangingBeaconsInRegion:self.scannerRegion];
}

-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
    //SCANNER HAS LEFT THE AREA
    [self.locationScanner stopRangingBeaconsInRegion:self.scannerRegion];
}

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
    CLBeacon *beacon = [[CLBeacon alloc] init];
    NSLog(@"Beacons: %d", [beacons count]);
    if(beacons && [beacons count]>0){
        beacon = [beacons firstObject];
    }
    else{

    }
}

The only limitation here is that the device cannot detect itself.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...