是否可以使用目标 C 扫描禁用位置服务的信标?
Posted
技术标签:
【中文标题】是否可以使用目标 C 扫描禁用位置服务的信标?【英文标题】:Is it possible to scan a beacon with location service disable using objective C? 【发布时间】:2016-09-21 13:26:49 【问题描述】:如果打开蓝牙和定位服务,我可以成功扫描信标。但我想知道当蓝牙处于开启模式且位置服务处于关闭模式时,有什么方法可以扫描信标。
我已经使用了这段代码,但是当位置服务关闭时,这个委托方法不会被调用
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
谁能详细说明我们如何在没有定位服务的情况下扫描信标?
提前致谢。
【问题讨论】:
是的,我猜你可以的。 【参考方案1】:在蓝牙开启但定位关闭的情况下,您只能使用CoreBluetooth
API 而非CoreLocation
API 来检测蓝牙 LE 信标设备。
这有效地阻止了您检测 iBeacon 传输,因为 ios 通过 CoreBluetooth
阻止了它们的检测。在此处查看我的博文:http://developer.radiusnetworks.com/2013/10/21/corebluetooth-doesnt-let-you-see-ibeacons.html
不过,您可以使用CoreBluetooth
来检测其他信标格式,例如 AltBeacon 和 Eddystone。我有开源代码显示如何使用iOS beacon tools 来做到这一点。
以下是使用上述工具扫描 AltBeacon、Eddystone-UID、Eddystone-URL 和 Eddystone-EID 并记录检测到的标识符的示例:
self.beaconParsers = [[NSMutableArray alloc] init];
RNLBeaconParser *altBeaconParser = [[RNLBeaconParser alloc] init];
[altBeaconParser setBeaconLayout:@"m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25" error: Nil ];
RNLBeaconParser *uidBeaconParser = [[RNLBeaconParser alloc] init];
[uidBeaconParser setBeaconLayout:@"s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19" error: Nil];
RNLBeaconParser *urlBeaconParser = [[RNLBeaconParser alloc] init];
[urlBeaconParser setBeaconLayout:@"s:0-1=feaa,m:2-2=10,p:3-3:-41,i:4-20v" error: Nil];
RNLBeaconParser *eidBeaconParser = [[RNLBeaconParser alloc] init];
[eidBeaconParser setBeaconLayout:@"s:0-1=feaa,m:2-2=30,p:3-3:-41,i:4-11" error: Nil];
self.beaconParsers = @[ altBeaconParser, uidBeaconParser, urlBeaconParser, eidBeaconParser ];
self.cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()
options:@ CBCentralManagerOptionRestoreIdentifierKey:
@"myCentralManagerIdentifier" ];
...
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
if (central.state == CBCentralManagerStatePoweredOn && self.scanning)
CBUUID *eddystone16BitUUID = [CBUUID UUIDWithString:@"FEAA"];
NSLog(@"eddy uuid is %@", [eddystone16BitUUID UUIDString]);
[self.cbManager scanForPeripheralsWithServices:@[eddystone16BitUUID] options:@CBCentralManagerScanOptionAllowDuplicatesKey : @(YES)];
// this scans for BLE peripherals including beacons
[self.cbManager scanForPeripheralsWithServices:nil options:@CBCentralManagerScanOptionAllowDuplicatesKey : @(YES)];
else
if (central.state == CBCentralManagerStateUnknown)
NSLog(@"CoreBluetooth state UNKNOWN");
else if (central.state == CBCentralManagerStateResetting)
NSLog(@"CoreBluetooth state RESETTING");
else if (central.state == CBCentralManagerStateUnsupported)
NSLog(@"CoreBluetooth state UNSUPPORTED");
else if (central.state == CBCentralManagerStateUnauthorized)
NSLog(@"CoreBluetooth state UNAUTHORIZED");
else if (central.state == CBCentralManagerStatePoweredOff)
NSLog(@"CoreBluetooth state POWERED OFF");
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
NSDictionary *serviceData = advertisementData[@"kCBAdvDataServiceData"];
RNLBeacon *beacon = Nil;
NSData *adData = advertisementData[@"kCBAdvDataManufacturerData"];
for (RNLBeaconParser *beaconParser in self.beaconParsers)
if (adData)
beacon = [beaconParser fromScanData: adData withRssi: RSSI forDevice: peripheral serviceUuid: Nil];
beacon.bluetoothIdentifier = [peripheral.identifier UUIDString];
else if (serviceData != Nil)
for (NSObject *key in serviceData.allKeys)
NSString *uuidString = [(CBUUID *) key UUIDString];
NSScanner* scanner = [NSScanner scannerWithString: uuidString];
unsigned long long uuidLongLong;
[scanner scanHexLongLong: &uuidLongLong];
NSNumber *uuidNumber = [NSNumber numberWithLongLong:uuidLongLong];
NSData *adServiceData = [serviceData objectForKey:key];
if (adServiceData)
beacon = [beaconParser fromScanData: adServiceData withRssi: RSSI forDevice: peripheral serviceUuid: uuidNumber];
if (beacon != Nil)
break;
if (beacon != Nil)
NSString *key = [NSString stringWithFormat:@"%@ %@ %@", beacon.id1, beacon.id2, beacon.id3];
NSLog(@"Detected beacon: %@", key);
【讨论】:
但是即使位置服务关闭,Crome 小部件也能够扫描 IBeacon。你能分享一下你在这背后的知识吗? Chrome 小部件扫描 Eddystone-URL 传输,而不是 iBeacon 传输。这就是为什么没有 CoreLocation 也能做到这一点的原因。在这里查看更多:developer.radiusnetworks.com/2015/07/22/… 查看我的答案编辑,其中包含指向测试的链接,证明您无法使用 CoreBluetooth 检测 iBeacon,以及使用 CoreBluetooth 检测其他信标格式的代码。 非常感谢。您能告诉我如何使用 CoreBluetooth 框架来扫描 Eddystone 信标吗? 抱歉,您根本无法在 iOS 上使用公共 API 扫描所有 iBeacon UUID。 Apple 故意不允许这样做。【参考方案2】:不,我认为您不能在关闭位置服务的情况下使用系统 iBeacon 支持。 iBeacon 支持由 Core Location 框架提供。
您也许可以编写低级 BLE 代码来查找来自 iBeacons 的消息,但我看到了一些人的帖子,他们无法弄清楚如何做到这一点。此外,您将失去 Core Location 提供的好处,例如即使在检测到信标时您的应用没有运行,也会收到有关信标的通知。
【讨论】:
感谢您的回答。但是即使位置服务关闭,Google Crome 是如何扫描信标的呢?正如我们在 Crome 小部件中看到的最近的信标。你能分享一下这背后的一些想法吗? 我怀疑他们有自己的 BLE 库来检测 iBeacons。【参考方案3】:不,您不能在没有定位服务的情况下使用 iBeacon。检查苹果文档是怎么说的:
iBeacon 与 iOS 中的定位服务一起使用。使用 iBeacon,您的 iOS 当您接近或离开某个位置时,设备可以提醒应用程序。在 除了监控您的位置,应用程序还知道您何时靠近 到 iBeacon,例如零售店的收银台。代替 使用纬度和经度来确定您的位置,iBeacon 使用 您的 iOS 设备检测到的低功耗蓝牙信号。
更多详情可以阅读Apple support for iBracon
希望这会有所帮助:)
【讨论】:
以上是关于是否可以使用目标 C 扫描禁用位置服务的信标?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以通过仅禁用该模块来支持在 4.3 之前版本上运行的 android 设备上使用信标技术的应用程序?