I'm using the air locate example and monitoring for iBeacons by uuid only. When I get the entered region event, I can't seem to get the major and minor from the beacon/region that has triggered the event if I'm only looking for the uuid (I can if I'm monitoring for a uuid with specified major and minor) - does anyone know a way to do this/am I missing something?
I don't really want to start ranging - doesn't seem like I should need to..
(The use case is for say lots of stores all with beacons with the same uuid, then issuing an OS notification with relevant information about that store (obtained by querying the major and minor))
Here's basically what I do:
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:@"blah"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
region.notifyEntryStateOnDisplay = YES;
[self.locationManager startMonitoringForRegion:region];
Then in the app delegate:
- (void) locationManager:(CLocationManager*)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion*)region {
// assume for now its the iBeacon
CLBeaconRegion *beaconRegion = (CLBeaconRegion*) region;
beaconRegion.major // hasn't been set...
}
Many Thanks!
The purpose of the major and minor are to subdivide the identifier space for logical purposes. If you then match solely on UUID or UUID and major, you can take diffrent actions depending on which beacon is detected by examining the minor value.
Major and Minor values Major and Minor are unsigned integer values between 1 and 65535. Major values are intended to identify and distinguish a group—for example all beacons on a certain floor or room in your venue could be assigned a unique Major value.
This protocol enables seamless interactivity between iOS and Android devices, and an iBeacon hardware, such as BLE beacons. iBeacon technology has been empowering businesses by letting them welcome customers, provide location-relevant information and promote ongoing offers.
You're not doing anything wrong. Surprising as it may seem, the monitoring API doesn't give you the specific beacon(s) that triggered the region change.
The reason the major isn't set on the CLBeaconRegion object is because that is the exact same object you used to start monitoring, and you set that field to nil (or didn't set it at all leaving it nil). What you are looking for is an additional array of CLBeacon objects. And as you suggest, this is only present on the Ranging APIs.
It really isn't a big deal to start ranging. Just set it up at the exact same time as you start monitoring:
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:@"blah"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
region.notifyEntryStateOnDisplay = YES;
[self.locationManager startMonitoringForRegion:region];
[self.locationManager startRangingBeaconsInRegion:region];
And if you only care about the first ranging call, you can use a flag to ignore further updates:
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
if (!_firstOneSeen) {
// Do something with beacons array here
}
}
And reset that flag when you leave the region
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
_firstOneSeen = NO;
}
As a bonus, this will also make your monitoring response times much faster when your app is in the foreground. See: http://developer.radiusnetworks.com/2013/11/13/ibeacon-monitoring-in-the-background-and-foreground.html
Unfortunately, determining the major and minor is only available in the iBeacon ranging API and not the iBeacon monitoring API if you monitored by UUID only. Furthermore,
1) iBeacon ranging does not work while your app is in the background. This means if your app is in the background (which is most of the time for these types of apps) you cannot determine the major and minor of an iBeacon unless you monitored based on UUID, major and minor.
2) You can only monitor a maximum of 20 iBeacons at the same time. This means if you resort to monitoring by UUID, major and minor (to get around the ranging in the background issue) you will be limited to only 20 iBeacons (a big limitation in most practical cases).
3) For maximum scalability (since you can only concurrently monitor 20 iBeacons) it would be best to monitor by UUID only, notify the user when an iBeacon of that UUID is detected and upon notification the user could acknowledge to bring the app into the foreground. Once the app is in the foreground ranging can occur to determine the major and minor of the iBeacon.
All of this leads me to wonder why Apple didn't include the array of iBeacons triggering the entry/exit in the monitoring API in the first place. I leave this for Apple to comment on. The following post goes into great detail on these iBeacon behaviors/limitations - iBeacon in the background - Use cases
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With