1、什么是iBeacon?
iBeacon 是苹果公司在 iOS 7 中新推出的一种近场定位技术,可以感知一个附近的 iBeacon 信标的存在。
当一个 iBeacon 兼容设备进入/退出一个 iBeacon 信标标识的区域时,iOS 和支持 iBeacon 的 app 就能得知这一信息,从而对用户发出相应的通知。
典型的应用场景例如博物馆实时推送附近展品的相关信息,商场内即时通知客户折扣信息等。苹果在 Apple Store 中也部署了 iBeacon 来推送优惠、活动信息。还可以应用的使用场景是将某个 iBeacon 发射器安装在你的电脑包、钱包甚至是你的猫的项圈上——即任何你不想丢失的重要物件。一旦你的设备离开发射器的范围,你的应用就会检测到并通知你。
2、UUID、主要、次要标识符
iBeacon 本质上来说是一个位置(区域)信息,所以 Apple 把 iBeacon 功能集成在了 Core Location 里面。
iBeacon 信标在 Core Location 中表现为一个 CLBeacon
,它圈定的范围则表现为 CLBeaconRegion
,这是一个 CLRegion
的子类。
CLBeaconRegion
主要用三个属性来标识一个 iBeacon,proximityUUID
、major
和 minor
。
iBeacon 在 CoreLocation 框架中抽象为CLBeacon类, 该类有6个属性,分别是:
-
proximityUUID,是一个 NSUUID,用来标识公司。每个公司、组织使用的 iBeacon 应该拥有同样的 proximityUUID。
-
major,主要值,用来识别一组相关联的 beacon,例如在连锁超市的场景中,每个分店的 beacon 应该拥有同样的 major。
-
minor,次要值,则用来区分某个特定的 beacon。
-
proximity,远近范围的,一个枚举值。
typedef NS_ENUM(NSInteger, CLProximity) {
CLProximityUnknown,// 无效
CLProximityImmediate,//在几厘米内
CLProximityNear,//在几米内
CLProximityFar//超过 10 米以外,不过在测试中超不过10米就是far
}
-
accuracy,与iBeacon的距离。
-
rssi,信号轻度为负值,越接近0信号越强,等于0时无法获取信号强度。
这些属性如果不指定(即 nil),匹配的时候就会忽略这个属性。例如只指定 proximityUUID
的 CLBeaconRegion
可以匹配某公司的所有 beacons。
只要进入iBeacon的范围,就能唤醒 App(大约10秒钟),即使在程序被杀掉的情况下。必要时,可以使用UIApplication类的- (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void (^)(void))handler;方法,请求更多的后台执行时间。
3、使用iOS设备作为iBeacon
如果手头没有iBeacon设备,任何支持蓝牙低功耗的IOS设备都可以作为iBeacon。
1.初始化peripheralManager
self.peripheralManager = [[CBPeripheralManageralloc] initWithDelegate:selfqueue:dispatch_get_main_queue() options:@{}];
CLBeaconRegion *beaconRegion = [[CLBeaconRegionalloc] initWithProximityUUID:[[NSUUIDalloc] initWithUUIDString:Beacon_Device_UUID] major:9999 minor:8888 identifier:@"0000"];
2.实现代理协议
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
NSLog(@"didUpdateState: peripheralState=%ld", (long)peripheral.state);
if (peripheral.state == CBManagerStatePoweredOn) {
[self hopPayload];
}
}
- (void)hopPayload {
if ([self.peripheralManagerisAdvertising]) {
[self.peripheralManagerstopAdvertising];
}
NSDictionary *beaconPeripheraData = [self.beaconRegion11 peripheralDataWithMeasuredPower:@(-50)];
[_peripheralManager startAdvertising:beaconPeripheraData];
}
3、相关代码
请求用户授权 (需要在info.plist文件中添加相关的权限 Privacy - Location Always Usage Description、Privacy - Location When In Use Usage Description、Privacy - Location Always and When In Use Usage Description)
引入 #import <CoreLocation/CoreLocation.h>
NSString * const Beacon_Device_UUID = @"E2C56DB5-DFFB-48D2-B060-D0F5A71096E0";
@property (strong, nonatomic) CLLocationManager *locationManager;
@property (strong, nonatomic) CLBeaconRegion *beaconRegion;
1.判断用户权限
BOOL availableMonitor = [CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]];
if (availableMonitor) {
CLAuthorizationStatus authorizationStatus = [CLLocationManager authorizationStatus];
switch (authorizationStatus) {
case kCLAuthorizationStatusNotDetermined:
{
NSLog(@"这台设备可以检测到周围的beacon");
[self.locationManager requestAlwaysAuthorization];
}
break;
case kCLAuthorizationStatusRestricted:
case kCLAuthorizationStatusDenied:
NSLog(@"受限制或者拒绝");
break;
case kCLAuthorizationStatusAuthorizedAlways:
case kCLAuthorizationStatusAuthorizedWhenInUse:
[self startMonitoring];
break;
}
} else {
NSLog(@"该设备不支持 CLBeaconRegion 区域检测");
}
2.创建CLLocationManager对象
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
3.创建圈定的范围区域对象CLBeaconRegion
_beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:Beacon_Device_UUID] identifier:@"test"];
根据需求用那种方式创建:
// 仅使用proximityUUID来初始化区域,major,minor值将作为通配符。只要是区域内的iBeacon的proximityUUID与此proximityUUID相同,不管major, minor是什么值,都能被检测到。
- (instancetype)initWithProximityUUID:(NSUUID *)proximityUUID identifier:(NSString *)identifier;
//使用proximityUUID和major来初始化区域,minor值将作为通配符。区域内的iBeacon的proximityUUID和major与此proximityUUID和major相同时,不论minor为何值,都能被检测到。
- (instancetype)initWithProximityUUID:(NSUUID *)proximityUUID major:(CLBeaconMajorValue)major identifier:(NSString *)identifier;
//使用proximityUUID, major, minor来初始化,只能检测到区域内相同proximityUUID, major, minor的iBeacon设备。
- (instancetype)initWithProximityUUID:(NSUUID *)proximityUUID major:(CLBeaconMajorValue)major minor:(CLBeaconMinorValue)minor identifier:(NSString *)identifier;
4.可用两种方式检测区域 Monitoring或Ranging方式
第一种:
[self.locationManager startMonitoringForRegion:self.beaconRegion];
#pragma mark - Monitoring:可以用来在设备进入/退出某个地理区域时获得通知, 使用这种方法可以在应用程序的后台运行时检测 iBeacon,但是只能同时检测 20 个 region 区域,并且不能够推测设备与 iBeacon 的距离。
// Monitoring成功对应回调函数
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(nonnull CLRegion *)region {
NSLog(@"Monitoring成功");
}
// Monitoring有错误产生时的回调
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(nullable CLRegion *)region withError:(nonnull NSError *)error {
NSLog(@"Failed monitoring region: %@", error);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(@"Location manager failed: %@", error);
}
// 设备退出该区域时的回调
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(@"设备出了你的范围了");
}
// 设备进入该区域时的回调
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(@"设备进入你的范围了");
NSLog(@"*******enter region:%@",region.identifier);
}
第二种:
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
#pragma mark -- Ranging:可以用来检测某区域内的所有 iBeacons
//manager监测当前进入范围的beacon
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
}
GitHub地址:https://github.com/KunlunLu/BeaconDemo