iOS beacon region monitoring require to enable bluetooth - ios

I am developing an app which has beacon region monitoring.Below is the code for monitoring beacon region.
-(void)setBeaconMonitoringForUUID:(NSString *)strID withMajor:(NSString *)strMajor withMinor:(NSString *)strMinor withIdentifier:(NSString *)strIdentifier {
NSUUID *strUUID = [[NSUUID alloc] initWithUUIDString:strID];
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:strUUID major:[strMajor intValue] minor:[strMinor intValue] identifier:strIdentifier];
[beaconRegion setNotifyEntryStateOnDisplay:YES];
[beaconRegion setNotifyOnEntry:YES];
[beaconRegion setNotifyOnExit:YES];
[self.objLocationManager startMonitoringForRegion:beaconRegion];
[self.objLocationManager startRangingBeaconsInRegion:beaconRegion];}
and the locationManager initialization is as below
- (id)init
{
self = [super init];
if (self != nil)
{
self.objLocationManager = [CLLocationManager new];
self.objLocationManager.delegate = self;
self.objLocationManager.distanceFilter = 10.0;
self.objLocationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
self.objLocationManager.allowsBackgroundLocationUpdates = YES;
if ([self.objLocationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.objLocationManager requestAlwaysAuthorization];
}
[self.objLocationManager startUpdatingLocation];
}
return self;
}
Now the question is for monitoring beacon region the iOS device must have to enable bluetooth or its working without turn on bluetooth?.I have also refer the below link but there is no explanation about to enable bluetooth for region monitoring
Determining the Availability of Region Monitoring
I have test with kontakt.io beacon and its not working without turning on bluetooth on device but as i read the region monitoring is working on Location service then why we need to enable bluetooth.so every beacon require to turn on bluetooth or it is specific to kontakt.io beacon?

Apple made a change in iOS 11 so that even if the user disables bluetooth in Control Center, scans for and detections of iBeacon devices are still performed by the operating system. (Control Center is the quick access pane you get by swiping up from the bottom of the screen on iOS.) See here for more details: https://support.apple.com/en-us/HT208086
The above statement is not true for iOS 10.x and earlier, where turning off bluetooth in Control Center will disable beacon detection. And as #Paulw11 states in his answer, you must also have location enabled on the phone, and the app must obtain a dynamic location permission from the app before it can detect beacons.
Also on all versions of iOS, if you go to Settings -> Bluetooth and disable bluetooth it will disable beacon detection.

iBeacons use Bluetooth Low Energy to advertise themselves, so the Bluetooth setting on the iOS device must be on in order to receive the signal.
Since detection of a beacon can be used to determine a user's location by correlating the detection of a beacon with the known location of the beacon you must obtain the user's permission to use their location.

Related

Estimote beacon... didEnterInRegion doesn't call in Background

I need to work with an Estimote beacon.
When the app is in foreground LocationMangaer delegate method didEnterInRegion end didExitRegion are called properly, but I have a problem when the application is in background (with locked screen).
If I leave the device on a table and if I walk away with Estimate beacon, after a few meters the method didExitRegion is called.
When I approach to the device and enter in the region of the beacon (a few centimeters) the method didEnterInRegion or method didDetermineState aren't called never. If I unlock the screen, after a few seconds, the method didEnterInRegion are called.
This is my code:
NSUUID *beaconUUID = [[NSUUID alloc] initWithUUIDString:#"MYUUID"];
NSString *regionIdentifier = #"FuelPay";
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:beaconUUID identifier:regionIdentifier];
beaconRegion.notifyOnExit = YES;
beaconRegion.notifyOnEntry = YES;
beaconRegion.notifyEntryStateOnDisplay = YES;
self.locationManager = [[CLLocationManager alloc] init];
if([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[self.locationManager requestAlwaysAuthorization];
}
self.locationManager.delegate = self;
self.locationManager.pausesLocationUpdatesAutomatically = NO;
[self.locationManager startMonitoringForRegion:beaconRegion];
In the Info.plist I set NSLocationAlwaysUsageDescription property and I enable background mode (with "Uses Bluetooth LE accessories") in project capabilities.
What is wrong?
Thank you very much!
Background monitoring is NOT the same as foreground monitoring. It may take a while (in the order of minutes also) to detect a beacon in background since the scanning ratio is reduced (otherwise your battery will drain too fast).
Try your tests waiting a little bit more, if didExitRegion is called it's counterpart didEnterRegion should be called too.
Anyway I assume that before you check the didEnterRegion you have previously performed an exit. I mean that if you launch your app while you are already within the range of a beacon (e.g. beacon and device in the same room) there is no way didEnterRegion will ever be called. So you can
Trigger didExitRegion leaving the room
Launch your app without any beacon in range
and then get close to your beacon again

How to get indoor location X and Y postion when app runs in Background?

Currently I am working on Estimote indoor location SDK to use indoor location service and I am getting X and Y position when app is foreground but i want to also get X and Y position when application is background so its possible in Estimote indoor SDK.
You will find an answer in Swift here
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
CLBeaconRegion *region;
region = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:#"2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6"] major: 1 minor: 1 identifier: #"region1"];
region.notifyEntryStateOnDisplay = YES;
[_locationManager startMonitoringForRegion:region];
[_locationManager startRangingBeaconsInRegion:region];
return YES;
}
You must adapt this code to use the Estimote Indoor Location SDK
Unless you keep your app running in the background (e.g. by using regular location services at the same time … or uh, playing music), Indoor Location won't have access to real-time RSSI readings from beacons and iDevice's sensors, which means it'll be unable to compute your (x,y) location. Just keep in mind you need a very, very good reason (e.g. you actually are building a music player which changes the music based on the indoor position) to keep your app alive in the background, otherwise the it'll get rejected during the app review process.

Is it possible to allow iBeacon app work properly without GPS?

I've been working on iOS app which interacts with iBeacon devices. Workflow is next:
if user near iBeacon then app receiving push notification from internet.
So for recognizing if user near some iBeacon needs to be turned on next modules:
gps
bluetooth
wifi/3G
push notification
The issue is that without turned on GPS module app can't find any iBeacons. It's weird since iBeacon technology works using bluetooth only.
How to solve the following problem?
I use Xcode 6.1.1, iOS 8, CoreLocation and CoreBluetooth frameworks.
Here is a code how I implemented:
if ([CLLocationManager locationServicesEnabled]) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
if([_locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
[_locationManager requestAlwaysAuthorization];
}
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"12345678-1234-1234-1234-123456789012"];
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:bundleIdentifier];
[_locationManager startMonitoringForRegion:beaconRegion];
[_locationManager startRangingBeaconsInRegion:beaconRegion];
}
else {
NSLog(#"location service is disabled");
}
You don't need GPS for iBeacon to work, but you do need Location Services.
This why I asked how you were "turning off the GPS", as I am not aware of any way in iOS that you can turn off the GPS receiver specifically.
When the user disables Location Services in the Settings app they aren't just turning off GPS - as the name says, they are turning off Location Services. Location Services in iOS refers to anything that can locate the user, which includes GPS, WiFi location and iBeacon.
No, without GPS, iBeacon will not work properly. CLLocation Manager is a class in the core location framework. The delegates of CLocation Manager will not get triggered without GPS. Here iBeacon works with the help of CLocation Manager.
- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region;
This is the delegate that is getting triggered while an iBeacon is identified in a region. This delegate will not work without GPS.

IBeacon region monitoring not work consistently across devices

When testing with a simple app to test beacon region monitoring I seem to get very inconsistent results depending on the device (not the device model, the specific device). The problem is that I don't receive the CLRegionStateInside state on the region after requestStateForRegion and didEnterRegion does not get called at all on these device. startRangingBeaconsinRegion: works fine but to conserve power and processing it is recommended to only start ranging when the didEnterRegion: method gets called. I tested this on 6 devices and it works on half on them (iPhone 5's) and does't work on one iPhone 5, one 5S and one 4S.
The beacons I use are the kontakt.io beacons.
This is the code to setup the region monitoring
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:BEACON_UUID];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid
identifier:#"regionIdentifier"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
region.notifyEntryStateOnDisplay = YES;
[self.locationManager startMonitoringForRegion:region];
[self.locationManager requestStateForRegion:region];
//If I enable this line, ranging starts on all devices
// [self.locationManager startRangingBeaconsInRegion:region];
I Found the problem. Apparently to use iBeacons in the way that is described in the documents users are required to have the Background Refresh setting enabled in the Settings. To check for this setting I use the following snippet:
if ([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusAvailable) {
NSLog(#"Background updates are available for the app.");
}else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusDenied)
{
NSLog(#"The user explicitly disabled background behavior for this app or for the whole system.");
}else if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted)
{
NSLog(#"Background updates are unavailable and the user cannot enable them again. For example, this status can occur when parental controls are in effect for the current user.");
}
Found in this answer: Detecting user settings for Background App Refresh in iOS 7
Monitoring may not work for several reasons. One being that App Background Refresh is disabled to save your battery. Another one is neglecting to ensure you have setup the correct App Capabilities.
If this doesn't work there is a great post you can read that details all of the items to troubleshoot.
iBeacon StartMonitoringForRegion Doesn’t Work

Ranging Beacons only works when app running?

I am having difficulties getting this to work for when the app is not running. I have locationManager:didRangeBeacons:inRegion: implemented and it is called when the app is running in the foreground or background, however it doesn't seem to do anything when I quit the app and lock the screen. The location services icon goes away and I never know that I entered a beacon range. Should the LocalNotification still work?
I have Location updates and Uses Bluetooth LE accessories selected in Background Modes (XCode 5) I didn't think I needed them.
Any help greatly appreciated.
-(void)watchForEvents { // this is called from application:didFinishLaunchingWithOptions
id class = NSClassFromString(#"CLBeaconRegion");
if (!class) {
return;
}
CLBeaconRegion * rflBeacon = [[CLBeaconRegion alloc] initWithProximityUUID:kBeaconUUID identifier:kBeaconString];
rflBeacon.notifyOnEntry = YES;
rflBeacon.notifyOnExit = NO;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager startRangingBeaconsInRegion:rflBeacon];
[self.locationManager startMonitoringForRegion:rflBeacon];
}
-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
if (beacons.count == 0 || eventRanged) { // breakpoint set here for testing
return;
}
eventRanged = YES;
if (backgroundMode) { // this is set in the EnterBackground/Foreground delegate calls
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.alertBody = [NSString stringWithFormat:#"Welcome to the %# event.",region.identifier];
notification.soundName = UILocalNotificationDefaultSoundName;
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
// normal processing here...
}
Monitoring can launch an app that isn't running. Ranging cannot.
The key to having monitoring launch your app is to set this poorly documented flag on your CLBeaconRegion: region.notifyEntryStateOnDisplay = YES;
This can launch your app on a region transition even after completely rebooting your phone. But there are a couple of caveats:
Your app launches into the background only for a few seconds. (Try adding NSLog statements to applicationDidEnterBackground and other methods in your AppDelegate to see what is going on.)
iOS can take its own sweet time to decide you entered a CLBeaconRegion. I have seen it take up to four minutes.
As far as ranging goes, even though you can't have ranging wake up your app, you can make your app do both monitoring and ranging simultaneously. If monitoring wakes up your app and puts it into the background for a few seconds, ranging callbacks start up immediately. This gives you a chance to do any quick ranging actions while your app is still running.
EDIT: Further investigation proves that notifyEntryStateOnDisplay has no effect on background monitoring, so the above should work regardless of whether you have this flag. See this detailed explanation and discussion of delays you may experience
Code for iOS 9 to range beacons in the background, by using Location Updates:
Open Project Settings -> Capabilities -> Background Modes -> Toggle Location Updates and Uses Bluetooth LE accessories to ON.
Create a CLLocationManager, request Always monitoring authorization (don't forget to add the Application does not run in background to NO and NSLocationAlwaysUsageDescription in the app's info.plist) and set the following properties:
locationManager!.delegate = self
locationManager!.pausesLocationUpdatesAutomatically = false
locationManager!.allowsBackgroundLocationUpdates = true
Start ranging for beacons and monitoring region:
locationManager!.startMonitoringForRegion(yourBeaconRegion)
locationManager!.startRangingBeaconsInRegion(yourBeaconRegion)
locationManager!.startUpdatingLocation()
// Optionally for notifications
UIApplication.sharedApplication().registerUserNotificationSettings(
UIUserNotificationSettings(forTypes: .Alert, categories: nil))
Implement the CLLocationManagerDelegate and in your didEnterRegion send both startRangingBeaconsInRegion() and startUpdatingLocation() messages (optionally send the notification as well) and set the stopRangingBeaconsInRegion() and stopUpdatingLocation() in didExitRegion
Be aware that this solution works but it is not recommended by Apple due to battery consumption and customer privacy!
More here: https://community.estimote.com/hc/en-us/articles/203914068-Is-it-possible-to-use-beacon-ranging-in-the-background-
Here is the process you need to follow to range in background:
For any CLBeaconRegion always keep monitoring on, in background or foreground and keep notifyEntryStateOnDisplay = YES
notifyEntryStateOnDisplay calls locationManager:didDetermineState:forRegion: in background, so implement this delegate call...
...like this:
- (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region{
if (state == CLRegionStateInside) {
//Start Ranging
[manager startRangingBeaconsInRegion:region];
}
else{
//Stop Ranging
[manager stopRangingBeaconsInRegion:region];
}
}
I hope this helps.
You are doing two separate operations here - 'ranging' beacons and monitoring for a region. You can monitor for a region in the background, but not range beacons.
Therefore, your implementation of locationManager:didRangeBeacons:inRegion: won't get called in the background. Instead, your call to startMonitoringForRegion will result in one / some of the following methods being called:
– locationManager:didEnterRegion:
– locationManager:didExitRegion:
– locationManager:didDetermineState:forRegion:
These will get called in the background. You can at that point trigger a local notification, as in your original code.
Your app should currently wake up if you're just wanting to be notified when you enter a beacon region. The only background restriction I know of concerns actually hosting an iBeacon on an iOS device. In that case, the app would need to be physically open in the foreground. For that situation, you'd be better off just doing the straight CoreBluetooth CBPeripheralManager implementation. That way you'd have some advertising abilities in the background.

Resources