1

I have three brand new Kontakt.io beacons and used this tutorial and its source to try and identify them with my iPhone 4s. All I did is change the UUID (all Kontakt.io beacons had the same UUID fromt the start) and add some code:

This line is supposed to force the app to check also if it's already IN the region

[self.locationManager requestStateForRegion:self.myBeaconRegion];

These lines are supposed to check if the system is set up in the correct way:

NSArray *locationServicesAuthStatuses = @[@"Not determined",@"Restricted",@"Denied",@"Authorized"];
NSArray *backgroundRefreshAuthStatuses = @[@"Restricted",@"Denied",@"Available"];

BOOL monitoringAvailable = [CLLocationManager isMonitoringAvailableForClass:[self.myBeaconRegion class]];
NSLog(@"Monitoring available: %@", [NSNumber numberWithBool:monitoringAvailable]);

int lsAuth = (int)[CLLocationManager authorizationStatus];
NSLog(@"Location services authorization status: %@", [locationServicesAuthStatuses objectAtIndex:lsAuth]);

int brAuth = (int)[[UIApplication sharedApplication] backgroundRefreshStatus];
NSLog(@"Background refresh authorization status: %@", [backgroundRefreshAuthStatuses objectAtIndex:brAuth]);

When I start the app, with the iBeacons next to my phone, didEnterRegion is not fired. Also when I take out the battery and put them back in (to simulate going out of the range and going back in), nothing happens. Other Github-example codes didn't work for me either when using real iBeacons, only when I use another iPhone to transmit the signals.

This is the ViewController.h:

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

// Initialize location manager and set ourselves as the delegate
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;

// Create a NSUUID with the same UUID as the broadcasting beacon
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"A77A1B68-49A7-4DBF-914C-760D07FBB87B"];

// Setup a new region with that UUID and same identifier as the broadcasting beacon
self.myBeaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
                                                         identifier:@"com.appcoda.testregion"];

// Tell location manager to start monitoring for the beacon region
[self.locationManager startMonitoringForRegion:self.myBeaconRegion];

// Force app to check if it's already IN the region
[self.locationManager requestStateForRegion:self.myBeaconRegion];

// Check if beacon monitoring is available for this device
if (![CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) {

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Monitoring not available" message:nil delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [alert show]; return;
}

NSArray *locationServicesAuthStatuses = @[@"Not determined",@"Restricted",@"Denied",@"Authorized"];
NSArray *backgroundRefreshAuthStatuses = @[@"Restricted",@"Denied",@"Available"];

BOOL monitoringAvailable = [CLLocationManager isMonitoringAvailableForClass:[self.myBeaconRegion class]];
NSLog(@"Monitoring available: %@", [NSNumber numberWithBool:monitoringAvailable]);

int lsAuth = (int)[CLLocationManager authorizationStatus];
NSLog(@"Location services authorization status: %@", [locationServicesAuthStatuses objectAtIndex:lsAuth]);

int brAuth = (int)[[UIApplication sharedApplication] backgroundRefreshStatus];
NSLog(@"Background refresh authorization status: %@", [backgroundRefreshAuthStatuses objectAtIndex:brAuth]);
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion *)region
{
// We entered a region, now start looking for our target beacons!
self.statusLabel.text = @"Finding beacons.";
[self.locationManager startRangingBeaconsInRegion:self.myBeaconRegion];
}

-(void)locationManager:(CLLocationManager*)manager didExitRegion:(CLRegion *)region
{
// Exited the region
self.statusLabel.text = @"None found.";
[self.locationManager stopRangingBeaconsInRegion:self.myBeaconRegion];
}

-(void)locationManager:(CLLocationManager*)manager
   didRangeBeacons:(NSArray*)beacons
          inRegion:(CLBeaconRegion*)region
{
// Beacon found!
self.statusLabel.text = @"Beacon found!";

CLBeacon *foundBeacon = [beacons firstObject];

// You can retrieve the beacon data from its properties
//NSString *uuid = foundBeacon.proximityUUID.UUIDString;
//NSString *major = [NSString stringWithFormat:@"%@", foundBeacon.major];
//NSString *minor = [NSString stringWithFormat:@"%@", foundBeacon.minor];
}

This is the NSLog output:

2014-05-29 00:49:19.951 BeaconReceiver[2803:60b] Monitoring available: 1
2014-05-29 00:49:19.967 BeaconReceiver[2803:60b] Location services authorization status: Authorized
2014-05-29 00:49:20.109 BeaconReceiver[2803:60b] Background refresh authorization status: Available

Thanks a lot for your help!!

Leifcp
  • 55
  • 6

1 Answers1

2

Firstly, verify you can detect your beacons with an off-the-shelf app like Locate for iBeacon available here: https://itunes.apple.com/us/app/locate-for-ibeacon/id738709014?mt=8. It will verify that the beacons are working properly and the UUIDs are configured to be what you expect.

Once you know for sure the beacons work with your device, then start troubleshooting your code.

EDIT: Also be sure to reboot your phone before testing to guard against a known iOS 7.1 bug;: https://stackoverflow.com/a/22949187/1461050

Community
  • 1
  • 1
davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • I forgot to mention that I obviously checked the Kontakt.io app, which identified the beacons immediately. I have however tried to use "Locate for iBeacon" and entered the UUID mentioned above, but there nothing shows up. I also have an Estimote beacon which I can NOT find with the "Locate for iBeacon" app, although their UUIDs are standardized as well. When I however try [BLExplr](https://itunes.apple.com/us/app/blexplr/id524018027?mt=8), all beacons show up perfectly, but the app only shows the Bluetooth service UUIDs and not the iBeacon Proximity UUIDs. So my phone can theoretically find it – Leifcp May 29 '14 at 09:01
  • I am the author of Locate for iBeacon, so I can tell you that the app is a very simple wrapper around CoreLocation APIs. If you do not see the beacon with that app, I strongly suspect that the UUID being transmitted is not configured. If you think there is a possibility you do not have the UUID right, you could try the same app on Android (if you have an Android device) or our ScanBeacon product for Mac, as these allow detection of iBeacons without entering the matching UUID. Final note: see my edit about rebooting. – davidgyoung May 29 '14 at 13:29
  • Wow, it seems like its that iOS 7.1 bug, it works well after a restart. Thank you! – Leifcp May 29 '14 at 13:41