iOS CoreBluetooth / iBeacon: 同时广播iBeacon和外设服务

17
我正在为iOS编写一个应用程序,需要同时广告iOS iBeacon和周边服务。必须广告服务而不是仅在周边可发现,因为使用案例要求中央设备(BLE术语)在由于接近iBeacon而被iOS唤醒后(但仍在后台运行)连接到周边设备。在中央设备的后台运行的应用程序只能通过可用服务来发现周边设备,而无法发现所有周边设备[];我的代码可以广告服务或iBeacon,但我还没有找出如何同时进行两者广告的方法。可能iBeacon使用了38字节中的21字节可用空间,导致没有足够的空间广告信标和服务?
这个有效(beacon):
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid 
    major:1 
    minor:1 
    identifier:@"bentboolean"];
NSMutableDictionary *dict = [[self.beaconRegion peripheralDataWithMeasuredPower:nil] mutableCopy];    
[self.peripheralManager startAdvertising:dict ];

这个功能可用 (服务):

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

把两者结合起来,试图同时宣传两项服务是行不通的。这样只会宣传Beacon,而不是服务:

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 ];

感谢您的查看!


你好,你解决了这个问题吗?由于蓝牙的容量限制,我认为这是不可能的。 - CW0007007
2个回答

0
我能够使用单独的CLLocationManager和CLBeaconRegion为接收器和信标分别启动此操作:
#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{

    }
}

这里唯一的限制是设备无法检测自身。


我观察到的另一个有趣现象是:即使另一个应用程序宣传自己是iBeacon,你的应用程序也无法检测到它。更重要的是,如果存在外部iBeacon广告相同的标识符,你的应用程序仍然无法检测到它。换句话说,广告iBeacon ID集会阻止任何相同ID集的检测。 - davidgyoung
我观察到另一个有趣的现象:即使另一个应用程序宣传自己是iBeacon,你的应用程序也无法检测到它。如果我说错了,请纠正我,但在7.1版本中这已经不再是真实情况了。 - decades
(此评论已被删除) - decades
  • (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region { [self.locationManager startRangingBeaconsInRegion:self.scannerRegion]; } 你需要将 self.beaconRegion 替换成 self.scannerRegion 才能使其工作 :)
- decades
2
我不确定这个回答怎么能接近回答问题。问题是:“我能把自己作为信标和带服务的BLE外设进行广告吗?”这个回答讨论了将自己作为信标进行广告和尝试检测信标。 - Michael McGuire
显示剩余3条评论

0
在我的实践中,iBeacon 和 BLE 服务不能同时进行广播。
如果BLE服务与iBeacon混合广播,则无法在前台广播。 iBeacon无法在后台广播。
iBeacon和BLE服务可以依次广播,例如iBeacon广播0.5秒,然后 BLE服务广播30.0秒。
希望这会有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接