Jonathan Chen
Jonathan Chen

Reputation: 716

Can't detect when iBeacon bluetooth is turned off iOS

I'm writing two simple apps. One is a beacon app whose signal you can start or stop with the touch of a button. The other is a receiver app that edits the text of a label when it detects the signal of a beacon.

I've tried using the didDetermineStateForRegion, didExitRegion, and didEnterRegion methods to detect when an app is running. These work fine for determining when the receiver moves in and out of proximity of the beacon, but it takes roughly 30 seconds to determine that I've turned the bluetooth on the beacon off. I've also tried setting my CLLocationManager's pausesLocationUpdatesAutomatically field to NO, but same thing. Ideally, it'd just immediately put "No" to my label; how do I do this?

MyView.h

@interface MyView : UIViewController

@property (weak, nonatomic)   IBOutlet UILabel *statusLabel;
@property (strong, nonatomic) CLBeaconRegion   *myBeaconRegion;
@property (strong, nonatomic) CLLocationManager *locationManager;

@end

MyView.m

- (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;
    self.locationManager.pausesLocationUpdatesAutomatically=NO;

    // Create a NSUUID with the same UUID as the broadcasting beacon
    NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@"ID"];

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

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

- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion*)region
{
[self.locationManager startRangingBeaconsInRegion:self.myBeaconRegion];
self.statusLabel.text = @"Yes";
}

- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if (state == CLRegionStateInside) {
    self.statusLabel.text = @"Yes";
} else {
    self.statusLabel.text = @"No";
}

}

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

Upvotes: 0

Views: 1319

Answers (1)

csexton
csexton

Reputation: 24793

Region monitoring is pretty slow, you can use it for more general notification to let you know when you are near an iBeacon. I think for this case you would want to use didRangeBeacons, where your detection app will be notified of the beacon signal strength every second. You can use this signal strength to decide if you no longer see the beacon (CoreLocation tends to still "see" the beacon a few seconds after it disapears).

Just add the following method to your delegate:

-(void)locationManager:(CLLocationManager*)manager
       didRangeBeacons:(NSArray*)beacons
              inRegion:(CLBeaconRegion*)region

And start ranging for your region with:

[locationManager startRangingBeaconsInRegion:(CLBeaconRegion*)region];

Upvotes: 2

Related Questions