I am Ahmet. I have been trying to solve a problem for 3 days, that I have about communicating with Estimote beacon first time. (I am quite new on beacons), I have read a lot of articles and looked for many example codes. Even tried the Estimote example app (provided in the Estimote SDK file). Some how I could not find the beacons through the code that I have written and example code (app) in the SDK file. But estimote application on the app store works fine.
I am using MacBookPro late 2011 version.
If you help me about this, I would appreciated that. My purpose is to communicate first, then the rest will come. I cannot go out from the house, so I have written the code in that way.
Here is the code that I am using.
//MainViewController.h
#interface MainViewController : UIViewController<CLLocationManagerDelegate>
#property(nonatomic, strong)CLBeaconRegion *beaconRegion;
#property(nonatomic, strong)CLLocationManager *locationManager;
#end
#implementation MainViewController
(void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
[self initRegion];
[self locationManager:self.locationManager didStartMonitoringForRegion:self.beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
NSLog(#"did start monitoring");
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
-(void)initRegion
{
NSLog(#"Init Region");
NSUUID *uuid = [[NSUUID alloc]initWithUUIDString:#"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];
self.beaconRegion = [[CLBeaconRegion alloc]initWithProximityUUID:uuid identifier:#"identifier"] ;
[self.locationManager startMonitoringForRegion:self.beaconRegion];
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
{
NSLog(#"Did enter region"); // never called
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
{
NSLog(#"Did exit region"); // never called
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
NSLog(#"NO Beacon Found...");
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
NSLog(#"did range Beacons");
CLBeacon *beacon = [[CLBeacon alloc]init];
beacon = [beacons lastObject];
NSLog(#"BEACON FOUND");
NSLog(#"Proximity UUID: %#",beacon.proximityUUID.UUIDString);
NSLog(#"MAJOR ID: %#", beacon.major);
NSLog(#"MINOR ID: %#", beacon.minor);
}
#end
According to MacTracker, your MacBookPro is not compatible.
Apple put a Bluetooth Low-Energy chip in its MacBook Pro starting with the Mid 2012.
Since iBeacon use in reality BLE (which is hidden, at least in the iOS part: CLBeacon vs CoreBluetooth), you won't detect iBeacon with your MBP, except if you may have a special BLE chip (extern, as some USB one we can find in the market).
To verify if you laptop is BLE compatible, I'd suggest you read this on SuperUser.
Related
I'm using core location library in iOS for finding beacons, I'm in beacon region and the didRangeBeacons callback is triggering but it is always returning an empty array of beacons.
Please find the attached sample code. I have beacon immediate to iPhone, but still, beacon region state is inside when app opened and immediately it is changed to outside state and we are getting an empty array in didRangeBeacons. I have included both NSLocationWhenInUseUsageDescription. The NSLocationAlwaysUsageDescription keys are in the info.plist. The application has location permission set to "always". I'm using both Estimote and Kontakt beacons. OS version is iOS 11.2.6, Device iPhone 5s, Xcode 9.2.
#import "CoreLocationViewController.h"
#interface CoreLocationViewController ()
{
CLLocationManager *locationManager;
CLBeaconRegion *beacon_region;
}
#end
#implementation CoreLocationViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"CoreLocationViewController viewDidLoad");
NSUUID *ProximityUUID = [[NSUUID alloc] initWithUUIDString:#"b94f62c8-1af4-11e8-accf-0ed5f89f718b"];
beacon_region = [[CLBeaconRegion alloc] initWithProximityUUID:ProximityUUID identifier:#"abqwercds"];
[beacon_region setNotifyEntryStateOnDisplay:YES];
[beacon_region setNotifyOnExit:YES];
[beacon_region setNotifyOnEntry:YES];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
if ([CLLocationManager locationServicesEnabled]){
NSLog(#"Location Services Enabled");
if(IS_OS_8_OR_LATER){
NSLog(#"We are in LocationServicesRequestViewController IS_OS_8_OR_LATER");
NSUInteger code = [CLLocationManager authorizationStatus];
NSLog(#"CLLocationManager authorizationStatus %lu",(unsigned long)code);
if (code == kCLAuthorizationStatusNotDetermined) {
NSLog(#"kCLAuthorizationStatusNotDetermined");
[locationManager requestAlwaysAuthorization];
}
}else{
NSLog(#"We are in LocationServicesRequestViewController IS_OS_8_BELOW");
}
}else{
NSLog(#"authorizationStatus ");
}
}
#pragma mark Location Manager Delegate methods
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error{
NSLog(#"locationManager Error %#",error);
}
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
NSLog(#"Status of location service is %d",status);
if ((status == kCLAuthorizationStatusAuthorizedAlways) || (status == kCLAuthorizationStatusAuthorizedWhenInUse)){
NSLog(#"location service status changed 1");
[locationManager startMonitoringForRegion:beacon_region];
[locationManager requestStateForRegion:beacon_region];
}else{
NSLog(#"location service status changed 2");
}
}
-(void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
NSLog(#"CLLocationManager Beacon Region State Determine ");
switch (state) {
case CLRegionStateUnknown:
{
NSLog(#" CLLocationManager Region state is unknown %#",region);
[locationManager stopMonitoringForRegion:beacon_region];
break;
}
case CLRegionStateInside:
{
NSLog(#" CLLocationManager Region state is In-Side %#",region);
[locationManager startRangingBeaconsInRegion:beacon_region];
}
case CLRegionStateOutside:
{
NSLog(#" CLLocationManager Region state is Out-Side %#",beacon_region);
[locationManager stopMonitoringForRegion:beacon_region];
break;
}
}
}
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region{
NSLog(#" CLLocationManager Enter into Region %#",region);
[locationManager startRangingBeaconsInRegion:beacon_region];
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(#"didExitRegion location manager %#",region );
[locationManager stopMonitoringForRegion:beacon_region];
}
-(void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region{
NSLog(#"CLLocationManager Beacon Monitoring Started for the region %#",region);
}
-(void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error{
NSLog(#"CLLocationManager Monitoring of beacon region %# is failed, Error %#",region,error);
}
-(void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError *)error{
NSLog(#"CLLocationManager ranging of beacon region %# is failed, Error %#",region.proximityUUID,error);
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region{
NSLog(#"beacons %#",beacons);
}
I am experiencing a really weird bug working with iOS and iBeacon. I have a really simple BeaconManager that ranges beacons with particular UUID, major and minor values and performs some actions once it found them. My app seems to work properly until it continuously toggle the Bluetooth status and stop doing its job. The only visible result is that the Bluetooth icon in the status bar start flickering due to Bluetooth stopping and restarting.
Where to focus attention?
This is my class definition:
#import "BeaconManager.h"
#implementation BeaconManager
- (instancetype)init {
self = [super init];
if (self) {
NSURL *beep = [[NSBundle mainBundle] URLForResource:#"beep" withExtension:#"aiff"];
soundFileURLRef = (CFURLRef) CFBridgingRetain(beep);
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundFileObject);
// Initializes properties
beacon = [CLBeacon new];
foundBeacons = [NSMutableArray new];
_lastBeaconActionTimes = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)initRegion {
// Initializes the beacon region by giving it an UUID and an identifier
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:BEACON];
beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:#"beacon.region"];
// Starts looking for beacon within the region
[self.locationManager startMonitoringForRegion:beaconRegion];
}
- (void)checkBeacon {
if (!self.locationManager) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])
[self.locationManager requestWhenInUseAuthorization];
}
[self initRegion];
[self locationManager:self.locationManager didStartMonitoringForRegion:beaconRegion];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager startMonitoringForRegion:beaconRegion];
[self.locationManager startRangingBeaconsInRegion:beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
[self.locationManager startRangingBeaconsInRegion:beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
[self.locationManager stopRangingBeaconsInRegion:beaconRegion];
}
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error {
NSLog(#"Failed monitoring region: %#", error);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"Location manager failed: %#", error);
}
- (void)locationManager:(CLLocationManager *)manager
didRangeBeacons:(NSArray *)beacons
inRegion:(CLBeaconRegion *)region {
if (foundBeacons.count == 0) {
for (CLBeacon *filterBeacon in beacons) {
// If a beacon is located near the device and its major value is equal to 1000 (MAJOR constant)
if (((filterBeacon.proximity == CLProximityImmediate) || (filterBeacon.proximity == CLProximityNear)))
// Registers the beacon to the list of found beacons
[foundBeacons addObject:filterBeacon];
}
}
// Did some beacon get found?
if (foundBeacons.count > 0) {
// Takes first beacon of the list
beacon = [foundBeacons firstObject];
if (([beacon.major isEqualToNumber:[NSNumber numberWithInt:MAJOR]]) && ([beacon.minor isEqualToNumber:[NSNumber numberWithInt:MINOR]])) {
// Takes the actual date and time
NSDate *now = [[NSDate alloc] init];
NSString *key = [NSString stringWithFormat:#"%# %# %#", [beacon.proximityUUID UUIDString], beacon.major, beacon.minor];
NSDate *lastBeaconActionTime = [_lastBeaconActionTimes objectForKey:key];
if ((lastBeaconActionTime == nil) || ([now timeIntervalSinceDate:lastBeaconActionTime] > MINIMUM_ACTION_INTERVAL_SECONDS)) {
[_lastBeaconActionTimes setObject:now forKey:key];
// Plays beep sound
AudioServicesPlaySystemSound(soundFileObject);
if (self.delegate) {
// Performs actions related to the beacon (i.e. delivers a coupon)
[self.delegate didFoundBeacon:self];
}
self.locationManager = nil;
}
// else [self.locationManager stopMonitoringForRegion:region];
}
[foundBeacons removeObjectAtIndex:0];
beacon = nil;
}
}
#end
Can't say for sure this is the reason why Bluetooth keeps toggling, but this part is definitely suspicious:
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locationManager startMonitoringForRegion:beaconRegion];
[self.locationManager startRangingBeaconsInRegion:beaconRegion];
}
This is essentially an infinite loop. Once monitoring starts, iOS invokes the didStartMonitoring method … which starts monitoring for the very same region, which makes the iOS invoke the didStartMonitoring method again, which …
I'd start with removing the startMonitoringForRegion line from this part of your code.
I am getting data from and hardware iBeacon , in which i can program to change its UUID.
I know the UUID of the hardware, but i dont understand what is the identifier in :
[[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:#"com.name.iBeacon"];
Is it my app identifier, or something the iBeacon is transmitting(its name?)
I wonder if this is why its not working .
I have set everything and i can't even discover the iBeacon :
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"74278BDA-B644-4520-8F0C-720EAF059935"];
self.beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:#"com.company.iBeacon"];
[self.locationManager startMonitoringForRegion:self.beaconRegion];
[self locationManager:self.locationManager didStartMonitoringForRegion:self.beaconRegion];
Than these delegates, which are in the same class(should be in app delegate?) are never fired :
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
NSLog(#"ENTER");
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
NSLog(#"EXIT");
}
I have read that you have to go in and out from the area ??
Another issue is, Apple says every BLE has services,that includes characteristic, but than, in iBeacon, what are the major and minor values? characteristics of the same service ?
Got it ,
if([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
Must be done first .
Since the new iOS 8 beta release, I have not been able to successfully get a user's location. Prior to the update to iOS 8 I had no issues, but now it always returns 0.000000 as the current latitude and longitude. Is this just a bug in the new release? My code is listed below:
//from the .h file
#interface MasterViewController : PFQueryTableViewController<CLLocationManagerDelegate,UITextFieldDelegate, UISearchBarDelegate, UISearchDisplayDelegate> {
}
#property (nonatomic, strong) CLLocationManager *locationManager;
//from the .m file
#synthesize locationManager = _locationManager;
- (void)viewDidLoad {
[super viewDidLoad];
[self.locationManager startUpdatingLocation];
}
- (CLLocationManager *)locationManager {
if (_locationManager != nil) {
return _locationManager;
}
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
return _locationManager;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
}
UPDATE
This question has been answered (Location Services not working in iOS 8). For anyone still struggling with this, to maintain backwards compatibility with iOS 7, I used the code below:
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) { }
As mentioned in your update/comment, iOS8 requires you to use requestAlwaysAuthorization or requestWhenInUseAuthorization as well as a new NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key in Info.plist
But there is something else which is wrong in your code:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
It has been deprecated in iOS6 and you should now use this new delegate method instead:
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
You can then get the latest location with something like this:
CLLocation *newLocation = [locations lastObject];
I'm having an issue where my app will not fire the didEnterRegion event if I start the app within the region. If I start the app outside the region and then enter the region, it fires. If I start the app inside the region, then leave the region, then re-enter the region, it fires.
Any suggestions on how to get it to fire as soon as the app is opened if it's in the region would be much appreciated!
I suggest you to use this code
[locationManager requestStateForRegion:region];
And use the delegate method didDetermineState: to check if the state is CLRegionStateInside or CLRegionStateOutside.
I don't think you can do that.
But, you can get the current location and check if it's inside the region you're specifying yourself. CLCircularRegion has a containsCoordinate: method for this.
The first conclusion is that didEnterRegion is implemented consistently with its name. :)
Implement something like this in your CLLocationManagerDelegate:
- (void) locationManager: (CLLocationManager *) manager
didStartMonitoringForRegion: (CLRegion *) region
{
if ([self insideRegion: region location: manager.location])
[self locationManager: manager
didEnterRegion: region];
}
From apple's documentation:
Monitoring of a geographical region begins immediately after
registration for authorized apps. However, don’t expect to receive an
event right away, because only boundary crossings generate an event.
In particular, if the user’s location is already inside the region
at registration time, the location manager doesn’t automatically
generate an event. Instead, your app must wait for the user to cross
the region boundary before an event is generated and sent to the
delegate. To check whether the user is already inside the boundary
of a region, use the requestStateForRegion: method of the
CLLocationManager class.
So I ended up doing this:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) NSDictionary *regionDictionary;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// setup regions in case you have multiple regions
self.regionDictionary = #{#"com.test" : #"2FAE2A83-1634-443B-8A0C-56704F81A181"};
// setup location manager
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
//start monitoring for all regions
for (NSString *key in self.regionDictionary.allKeys) {
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:self.regionDictionary[key]] identifier:key];
[self.locationManager startMonitoringForRegion:beaconRegion];
}
}
- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion *)region {
if (region.identifier.length != 0) {
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:self.regionDictionary[region.identifier]] identifier:region.identifier];
[self.locationManager startRangingBeaconsInRegion:beaconRegion];
}
}
- (void)locationManager:(CLLocationManager*)manager didExitRegion:(CLRegion *)region {
if (region.identifier.length != 0) {
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:self.regionDictionary[region.identifier]] identifier:region.identifier];
[self.locationManager stopRangingBeaconsInRegion:beaconRegion];
}
}
- (void)locationManager:(CLLocationManager*)manager didRangeBeacons:(NSArray*)beacons inRegion:(CLBeaconRegion*)region {
// Beacon found!
CLBeacon *foundBeacon = [beacons firstObject];
NSLog(#"UUID:%#; major:%#; minor:%#;", foundBeacon.proximityUUID.UUIDString, foundBeacon.major, foundBeacon.minor);
}
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region {
if ([region isKindOfClass:[CLBeaconRegion class]] && state == CLRegionStateInside) {
[self locationManager:manager didEnterRegion:region];
}
}
- (void)locationManager:(CLLocationManager *) manager didStartMonitoringForRegion:(CLRegion *) region {
[manager requestStateForRegion:region];
}