iBeacons scanning in background mode in iOS? - ios

Please help me!
Can you explain how can I continue scan iBeacons after changing app mode to background?
Please write an example code (iOS)
Thanks)

You can't indefinitely scan for beacons while backgrounded. You can typically range for about 5 seconds if you detect that you enter a CLBeaconRegion, and you can configure your location manager to notifyEntryStateOnDisplay (it defaults to NO), so when the screen turns on, such as when the user hits the home button, you will get about 5 seconds up range updates then.

The code needed to monitor for beacons is the same whether you are in the background or the foreground. You set it up like this:
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc]
initWithProximityUUID:proximityUUID
identifier:identifier];
[locationManager startMonitoringForRegion:beaconRegion];
And then get callbacks to the locationManager:didEnterRegion: and locationManager:didExitRegion:
You can read more details here:
https://developer.apple.com/library/ios/documentation/userexperience/Conceptual/LocationAwarenessPG/RegionMonitoring/RegionMonitoring.html

Related

didExitRegion: 1.5 to 2 minute delay of called when my application is killed or in background in ios 10

i have to use estimote location beacon,iphone 5s,ios version 10.
didEnterRegion: method also called 30 to 40 seconds delay.
i have to use below code for monitoring ibeacon.
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"CFC52BF4-FD33-4569-B4B5-5E9C220514A2"];
CLBeaconRegion *region = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:1 identifier:#"Technostacks23"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
// launch app when display is turned on and inside region
region.notifyEntryStateOnDisplay = YES;
if ([CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]])
{
[_locationManager startMonitoringForRegion:region];
[_locationManager startRangingBeaconsInRegion:region];
}
[self.locationManager startUpdatingLocation];
#pragma mark - CoreLocation Delegate method
-(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
//local notification fire
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
//local notification fire
}
please guys tell me how to tackle this scenario.
Thanks
I don't think you can monitor a region at the same time you are ranging. I had this problem on a screen I made where I wanted to show the user if they are in range of the Beacon. I had to stop monitoring until they left the screen, then restart monitoring. If you don't need the events for ranging (how close the user is to the Beacon), I would leave that line off, it isn't necessary to get -didEnter and -didExit calls. You also shouldn't need -startUpdatingLocation either. That is only for active location calls.
Entry events typically fire right away. Exit events do have a 20-30 second delay once you lose signal to the Beacon.
It may be that you are burning up your background run time monitoring, after you run out of time it stops, opening the door for you get monitoring events.
Call the startRangingBeaconsInRegion method in the didEnterRegion delegate method so it wont range for beacons when it is not already in the beacons region this will help in power and battery consumption and i believe it would speed up region detection a little bit.
Edit your advertising interval of the beacon make it 350ms or less.
Check in your iPhone Settings tab for the apps that allow background App Refresh and Location Always and just reverse them to don't allow and make a test see if there would be a difference in detection performance.
But in all cases the 30 - 40 sec delay i find it normal depending on the number of apps that are already processing in the background and running out resources plus it would be even better depending on your app model to start notifying for a region entry after a couple of seconds to make sure also that he is in the region and didn't just pass by so quickly "Im talking for a super market model for instance".
But if this is not your case and you want to detect a region just by passing by i think the fastest you can get will be 15 - 20 sec depending on your device capability, speed, other background processing apps, and the beacons advertising time interval.

Beacon monitoring keeping location services on, indefinately. iOS

My iPhone app registers for significant location change. When on location change is called, I start beacon region monitoring for all the beacon in certain range of user's location.
My app needs to identify that user has entered into a beacon region (irrespective of whether app is running or not). To achieve this, we did following things:
-- set notifyEntryStateOnDisplay flag to true for beacon regions:
beaconRegion.notifyEntryStateOnDisplay = true;
-- set Required background modes in pList to bluetooth-central. for ref. this link
I am not sure what got it working. But it turns out our app does not turn location services off, once started.
Is it possible to get significant location change update and beacon region entered update when location service is off?
Do I need to set Required background modes to get this working in background?
When you using iBeacon to monitor for specific region it will always display location icon on status bar, even when app is closed.
To disable location service for your app try to call method bellow for all you registered regions when going to background:
- (void)stopMonitoringForRegion:(CLRegion *)region
And to use iBeacon in background you actually need not "bluetooth-central" mode but "location".
You do not need to keep background mode - location updates ON for beacon ranging.
For background execution, just use UIBackgroundTaskIdentifier and your code will work in background as well.
check my answer iBeacon ranging in the background? here.

iBeacon ranging in the background?

I have started to test out iBeacons using estimotes as beacons.
It's all running pretty good, but i'm struggling with getting the app to run properly in the background.
self.region = [[CLBeaconRegion alloc] initWithProximityUUID:self.uuid identifier: self.deviceID];
self.region.notifyEntryStateOnDisplay = YES;
[self.locationManager startMonitoringForRegion:self.region];
So this is the basic setup and for my test app i want to show a local notification when my phone is in immediate proximity of the beacon. My problem is that it won't work unless i include the line below.
[self.locationManager startUpdatingLocation];
Can anyone explain why that is or if i'm missing something about iBeacons?
You are mistaken. You don't need to call startUpdatingLocation in order to be called in the background.
When you're in the background it takes longer to get notified when you enter a region. If you want ranging calls, you have to issue the startRangingBeaconsInRegion call as well. As the other poster pointed out, you will only get a few seconds of ranging calls from the background when a new beacon is detected. (You get a didEnterRegion, followed by a few ranging calls, and then your app goes back to sleep.)
No, you are not missing anything. In background you app gets a very small amount of time to do ranging. From my personal experience, you get about 3 to 5 ranging callbacks. Thats it.
You do not need to call startUpdatingLocation method.
startMonitoringForRegion method starts monitoring the region only and call the didStartMonitoringForRegion delegate method to let you know when beacon enter/exit the region.
You need to call startRangingBeaconsInRegion method, which calls didRangeBeacons delegate method which gives you array of detected beacons with UUID, major, minor, rssi info of beacons.
For background execution, just use UIBackgroundTaskIdentifier and your code will work in background as well.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"=== DID ENTER BACKGROUND ===");
UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'");
}];
if (bgTask == UIBackgroundTaskInvalid) {
NSLog(#"This application does not support background mode");
}
else {
//if application supports background mode, we'll see this log.
NSLog(#"Application will continue to run in background");
}
}

locationManager:didEnterRegion and didExitRegion are never getting called :iBeacon

While testing with beacons (ios devices) i found the listener beacon giving some unexpected behavior. locationManager:didEnterRegion method is not getting called even if a beacon enters a region. But the locationManager:didRangeBeacons:inRegion: is getting called correctly, and detected beacons are shown there.
- (void)startListening{
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager setDelegate:self];
NSUUID *myProximityUUID = [[NSUUID alloc]
initWithUUIDString:IDENTIFIER];
_beaconRegion = [[CLBeaconRegion alloc]
initWithProximityUUID:myProximityUUID
identifier:kPFTransmitterIdentifier];
_beaconRegion.notifyEntryStateOnDisplay = YES;
_beaconRegion.notifyOnEntry =YES;
[self.locationManager startMonitoringForRegion:self.beaconRegion];
[self.locationManager requestStateForRegion:self.beaconRegion];
//[self.locationManager startRangingBeaconsInRegion:self.beaconRegion];
}
this is the code i have written.
i need to create a local notification when the listener app enters a particular region even if the app isn't running.
It's possible nothing is wrong with your code. I've noticed that if you turn your test beacon on when the detector is already inside the beacon region (next to it), you will NOT get any notification that you entered the beacon region. That's most likely because iOS did not detect a boundary crossing. iOS seems to notify when it detects that you have crossed the boundary between "out of region" and "inside region" (in either direction) and only then calls the appropriate delegate methods.
To test this, simply turn on your beacon but leave your detector OFF. Then, as indicated by davidgyoung above, walk 200 feet away from your beacon. THEN turn the detector ON and walk toward the beacon. You should get a "didEnterBeaconRegion" notification when you enter the region.
Another thing you can try is to implement the "locationManagerDidDetermineStateForRegion" delegate method, which is called whenever the state of a defined monitored region changes, which happens whenever you turn on your detector. If you do that, you should get a callback even if your detector is already inside the beacon region when initiated. But note this does not happen in the background so you still need the other callbacks as well.
Here's the troubleshooting procedure I would use:
First get it working in the foreground. Run your app in the foreground, and turn off your iBeacon (if it does not have a switch, then pull out the battery or take it 200 feet away.) Wait 10 seconds (you should get a out of region notification in this time) then turn back on your iBeacon and verify you get an in region notification. If you do not get one, I suspect there is something wrong with your callback definition. If this is the case, please post that code.
Once you have it working in the foreground, try to get it working in the background with the shoulder button. Always get the phone to a known state of not being in the region while being in the foreground (using the procedure above), because it takes a long time to make this happen in the background. Once you know you are out of the region, put your app into the background by turning off your screen. Then turn back on your iBeacon. Since you have _beaconRegion.notifyOnEntry =YES, you should get a callback within one second of when you force your display on by hitting the shoulder or home buttons.
Once you have this working, you can go on to letting the phone detect the presence in the background without hitting the shoulder button. Understand though, that this can take longer than you might expect. See this discussion for more details.
Have you registered your app for background location updates in the info.plist file? You need to add a row with the array UIBackgroundModes and add an item location: See reference
The didEnterRegion method not get called when using notifyEntryStateOnDisplay before monitoring sometimes.I also have tested this condition on my device.Probably you can test once without notifyEntryStateOnDisplay or notifyOnEntry condition .It will help.

didRangeBeacons method not getting called when display is Off

i'm working with ibeacons from couple of weeks, i was trying to post some local notifications , when the iphone hits the beaconregion(when proximity near).
It was working fine when the app is in background with locked and with display on, but when my display turns black ,
didRangeBeacons method stopped getting called.
I know by using the
region.notifyEntryStateOnDisplay = true;
we can get notified while the display on.
Is there any way that i can achieve posting notification while the app is background with locked and display off.
Please help me out.
It is totally possible to range beacons in background.
You can go around the limitation by setting this up together with your current location manager or creating a parallel one (which makes no difference, I think). You'll also need to enable background location updates capabilities at your project.
locationManager2 = [[CLLocationManager alloc] init];
locationManager2.delegate = self;
locationManager2.desiredAccuracy = kCLLocationAccuracyKilometer;
[locationManager2 startUpdatingLocation];
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
//Do nothing here, but enjoy ranging callbacks in background :-)
}
Now, you'll need to have a good explanation when Apple ask you why do you need the background location updates mode in your app. They're very picky with that.
If you have requested both beacon entry notifications and ranging, and you ENTER a new region while the screen is locked, you will get a didEnterRegion message (or possibly the didDetermineState message) followed by about 5 seconds of ranging messages. If the user doesn't wake up the device during those 5 seconds, the ranging messages stop.
Thus you can't really filter based on proximity to a beacon from the background. If you try to wait until you get a range value of near then more than likely you won't get it because the device stops sending your ranging messages before the user gets that close. You then won't get any more notifications about that beacon region until the user either leaves the region again or wakes up the phone and brings your app back to the foreground.
An app I'm working on posts a local notification when it receives a didEnterRegion (or didDetermineState) message. That causes the screen to light up, but doesn't seem to extend the amount of time you get ranging notices.
No, this is by design and reflects iOS's goal of conserving battery. You can only count on didRangeBeacons: while the app is foregrounded.
David Young has a pretty thorough writeup that may help clarify.
I have the same problem which Madhu has. Instead of didUpdateToLocation, I used didUpdateLocations which is worked for me. Now I am able to range beacons while the app is in background or terminated with locked and display off.
On iOS 8.4
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
//Do nothing here
}

Resources