iOS: beacons detection taking a long time - ios

I have an app where I'm scanning for beacons ( I know the UIIDs) and displaying them. The first few times I ran it I found the beacons almost immediately. But now each time I run it, it seems to take longer and longer to detect them. Even though I have the beacons sitting on the desk right next to the device.
I've tried replacing the batteries, changing from a iPhone to an iPad, checking a beacon scanning app on the Mac, rebuilding the app, etc. I also have a range of different beacons from different manufacturers and they all seem to have the same issue. Nothing seems to fix this.
My code basically looks like this:
let locationManager = CLLocationManager()
locationManager.delegate = self
let region = CLBeaconRegion(proximityUUID: UUID(uuidString:"61687109-905F-4436-91F8-E602F514C96D")!, identifier: "BlueCat beacon")
locationManager.startMonitoring(for: region)
And then I can wait for anything up to 5 or more minutes before any of the delegate methods get call.
This is the first time I've attempted to use beacons. Is this normal? Can it take a long time for a beacon to be seen by a device?

Under ideal conditions, didEnterRegion callbacks on iOS come within a few seconds of a beacon coming into range. Under less ideal conditions, these callbacks can take 15 minutes or more.
There are lots of things that can cause delays in detecting beacons when monitoring, and it's hard to say for sure without knowing exactly how you are testing. Two tips:
Hardware filter slots on iOS devices are limited and are on a first-come, first-served basis. If you have a bunch of beacon apps installed that have taken up these slots (or if your app has registered a bunch of regions), all these slots may have been taken up. Once hardware filter slots are gone, detections fall back to software scans that happen about every 15 minutes. Uninstall all apps (including yours) that may be holding on to these slots, then reinstall just your app.
Make sure you aren't "in region" when you put the app to the background. If iOS believes it is in the region, you won't get a new didEnterRegion callback until after it realizes it left the region and then entered again. The time for iOS to realize it exited the region is much longer than the time it takes to realize it entered. To ensure it realizes it exited the region, you should always range for beacons when the app is in the foreground, and leave the app ranging in the foreground for about a minute to ensure iOS realizes it is no longer in region (it usually takes 30 seconds of ranging to trigger an exit.) Only then should you put it in the background and turn on a beacon to measure detection times.

Related

didRangeBeacons is called even beacon is off

I am implementing the IOS application with swift 3.0 which can monitor nearby beacons. I have an issue relating didRangeBeacon function, Detail reproduces steps below:
1- Application has entered beacon region
2- beacon is turned off
3- In next 10 seconds, didRangeBeacon function is still called and response still has one beacon object.
So I can not recognize beacon is off immediately. How can I recognize beacon is off immediately?
In case of iBeacon, the area is defined by the range of one or more beacons. This allows more granularity and precision than regular geofencing—the latter being based on a mix of signals from cell towers, WiFi and GPS. Beacon geofences are also more responsive: “enter” events usually take up to a few seconds to trigger, “exit” events up to 30 seconds. (Regular geofences take “3 to 5 minutes on average”, according to the CLLocationManager’s documentation.)
Testing “enter” events involves making sure you’re “outside” the region. Enabling “flip to sleep” makes it easy to simulate going out of range. “Enter” events take up to a few seconds to trigger, while “exit” events take up to 30 seconds.
Region monitoring is pretty slow, you can use it for more general notification to let you know. 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).

Estimote beacons not working on Iphone as expected

OUR GOAL WITH ESTIMOTE BEACONS : We are planning to setup Estimote beacons in golf course. our scenario is whenever player reaches the hole and what is the pace of play, It should be detected by the beacon & respond to the server through our IPhone application.
In this case user doesn't need to open the app, because mobile is in his pocket & he is playing.
WHAT WE HAVE DONE SO FAR:
Ranging only works when the app is in only active state. (GOAL NOT ACHIEVED).
To achieve this goal we are using Monitoring, but the problem is monitoring delegate (didDetermineState state: for region:) some times called some times not (called: instantly, someDelay & never). In other words beacons don't always detect by iOS by monitoring. (GOAL NOT ACHIEVED).
If we are testing on two or more iPhones 6s with same iOS versions 10, each phone have different results some detects & others not. For testing we used flip to sleep & setup beacons in different locations to be enter/exit events fired & lowest advertising interval.
Implemented edystone on estimote beacons, they are not working when application is in background. (GOAL NOT ACHIEVED).
We tried following solutions found on internet or forums of estimote beacons.
Its Nov 2013 article Ibeacon monitoring but in Dec 2016 it seems no difference.
We also tried for background ranging through CoreLocationManager.startUpdatingLocation:
Here and Here
We tried to speak Estimote but they answer was ambigious, "We're painfully aware that iBeacon monitoring can be a bit finicky at times. We hate it as much as developers trying to build beacon-powered apps do, but when it comes to iBeacon, we're quite helpless, because Apple has the API on lockdown—there's no way to detect iBeacon packets on iOS other than through the built-in API, which exhibits these problems."
It seems like some how it is possible.
This is how i am registering array of beacons currently we have 3 to 6 beacons.
func loadBeacons() { // Load beacons
self.beacons = getAllbeacons()
self.beaconManager = ESTBeaconManager()
self.beaconManager.delegate = self
self.beaconManager.requestAlwaysAuthorization()
if self.beaconManager.isAuthorizedForMonitoring() == true {
self.rangingBeaconsSetup()
} else {
self.beaconManager.requestAlwaysAuthorization()
}
}
func rangingBeaconsSetup() { // SET UP Ranging beacons
for beacon in self.beacons {
if let beaconRegion = self.beaconRegionFromItem(beacon) {
beaconRegion.notifyEntryStateOnDisplay = true
self.beaconManager.startMonitoring(for: beaconRegion)
self.beaconManager.startRangingBeacons(in: beaconRegion)
}
}
}
func beaconRegionFrom(_ beacon: Beacon) -> CLBeaconRegion? { // GET VALID REGION
let val = 1 << 16
if let uuid = NSUUID(uuidString: beacon.uuid), beacon.major < val && beacon.minor < val {
return CLBeaconRegion(proximityUUID: uuid as UUID, major: CLBeaconMajorValue(beacon.major), minor: CLBeaconMinorValue(beacon.minor), identifier: beacon.deviceName)
}
return nil
}
func beaconManager(_ manager: Any, didDetermineState state: CLRegionState, for region: CLBeaconRegion) { // Monitoring delegate.
if state == .inside {
let notification = UILocalNotification()
notification.alertBody = "By tapping you will be able to check-in"
notification.alertAction = "OK"
notification.fireDate = Date()
application.scheduleLocalNotification(notification)
}
}
These are following responses we receive when we have same IOS devices (OS 10) both have inconsistant behaviour.
RELATED QUESTIONS :
Is our expectation for beacon accuracy is quite high?
If a beacon is broadcasting the data to all the phones then every device must behave same because we have same IOS version, same Iphone and same code.
How can we get consistant results
Our experience is, Detection varies "from few seconds to 15 minutes and some time it does not detect at all"
What can we do to get consistant and reliable results?
From your problem description, the core problem you have is inconsistent behavior in background monitoring callbacks.
In theory, you should be able to to get a monitoring callback that wakes up your app in the background and lets it range in the background for 10 seconds (extendable to 3 minutes if you use this technique) each time a beacon is first detected in a monitored region or each time all beacons stop being detected in a monitored region. This will fire a didEnterRegion or didExitRegion callback.
As you have seen, sometimes these callbacks do not come when expected. There are two primary reasons for this:
You don't get a entry or exit callback because the region state has not changed. This often happens when iOS believes it was always inside a CLBeacon region, whereas an app tester briefly removed the iOS device from the vicinity of the beacon (either by moving the phone or turning the beacon off) and then returning it to the region. The failure to get an exit/entry sequence in this case is often caused by not giving iOS enough time to detect it has exited the region. In the background, this can take up to 15 minutes. Most of the time this is purely a testing problem and not a problem your actual users will face -- testers are under time pressure to get their tests done, so they often just don't wait long enough in thse test cases. Adding logging, notifications or other insight for when region exits occur can help your testers make sure they wait long enough.
You don't get an entry callback quickly because all hardware acceleration slots are filled. In order to detect becacons and send didEnterRegion callbacks within a second or two, iOS relies on Bluetooth hardware filters to wake up the OS when a beacon of interest is detected. The problem is that these hardware filters are a scarce resource, and if they are exhausted by other apps that were installed on the phone first, then your app won't get access to them, meaning that detection times will fall back to software scans that can take up to 15 minutes. There is no way to know wheter your app has been granted access to these hardware filters, and even uninstalling and re-installing an app on your phone can change whether this is true, leading to inconsistent resuls. The number of available filters is undocumented, but some evidence suggests the number is 30, meaning only the first 30 CLBeaconRegions monitored on a phone get priority access.
In order to solve problem #2 in your tests, uninstall any other apps that you think may be monitoring for beacons, then reinstall your app. You should then get more consistent results.
Of course, you can't make real users uninstall other beacon apps, so they may still face these problems. But the good news is that most average users won't have a lot of beacon apps on their phones, so this is far less likely to happen to real users than it is to deveolopers or testers who often have lots of beacon apps on their phones.

Caveats for background iBeacon Region Ranging

Apple explicitly discourages background iBeacon Ranging:
To promote consistent results in your app, use beacon ranging only while your app is in the foreground.
If your app is in the foreground, it is likely that the device is in the user’s hand and that the device’s view to the target beacon has fewer obstructions.
Running in the foreground also promotes better battery life by processing incoming beacon signals only while the user is actively using the device.
Should I choose to go naughty and do some ranging in the background (after entering a beacon range when monitoring), what consequences should I expect? (except for the famous 10-seconds running window before being put to sleep again?
In most cases, there is no reason to worry about battery drain from casual background ranging.
I've read that statement before, but I don't think it makes any sense, and suspect it was written before the CoreLocation iBeacon design was complete. (The statement has been there since the iOS 7 beta.)
Apple iOS generally enforces that you can only range in the background for 10 seconds at a time, typically triggered by a CLBeaconRegion monitoring entry/exit event. Unless you app is in an extreme situation where it is seeing beacon regions enter and exit all the time, 10 seconds of background bluetooth scanning just can't use that much battery.
Of course, there are techniques where you could range more often, such as requesting location background mode for constant ranging, or requesting an extra 3 minutes of ranging time as described in my blog post here. If you use one of these techniques, you should probably test the impact of your app on battery. But I certainly wouldn't describe doing these things as being "naughty" as long as you do so responsibly.

How can I get major and minor numbers in one UUID on iOS background monitoring status?

We are using one UUID, and major and minor combinations for different actions.
And we need to know major and minor numbers in iOS background monitoring.
The ranging can get major and minor numbers but this needs launching delay and battery consuming. So this is not the proper solution for us because we want immediate detecting and low battery consuming.
So we want to get major and minor numbers in same UUID on iOS background monitoring status.
This mechanism is necessary because we make an iOS application not for typical usage.
Is it possible?
You cannot read individual beacon identifiers using monitoring APIs. All you can do is access the CLBeaconRegion identifiers used to start monitoring. In your case, this is probably just the ProximityUUID with a nil major and minor.
The alternative is to combine ranging with background monitoring. Whenever you get a didEnterRegion event, you will also get ranging callbacks for about 10 seconds afterward, even if your app is in the background. You can use this callback to read all the identifiers.
While it is true that ranging in the foreground uses much more battery than monitoring, background ranging is actually pretty battery friendly. Consider that you will be only ranging for 10 seconds each time you enter or exit a region. (Even though ranging is still turned on, the OS automatically stops it after 10 secs in the background.) Unless you expect user to be constantly entering/exiting regions, then battery should not be a concern with such short periods of background ranging.

How long does it take to detect an iBeacon while region monitoring?

Take this scenario: user has an iPhone in the pocket passing by an iBeacon. Her phone is region monitoring for it. How much time is needed in real world to from entering the region to the moment app is woken up?
I have found an excellent article on the subject by David G. Young (http://developer.radiusnetworks.com/2013/11/13/ibeacon-monitoring-in-the-background-and-foreground.html) but I can't believe it can really take up to 15 minutes.
That would mean that all iBeacon home automation scenarios are simply unusable because you won't neither wait 15 mitutes in dark room for lights to switch on neither you would switch on the lights by actively using an app. Door opening and locking is another situation where iBeacon would be unusable (and NFC would work much better here). Or am I missing something?
I have an app that ranges for an iBeacons. It first grabs a list of couple proximityUUIDs and registers them as monitored regions.
When the device enters that region, it takes just 1 to several seconds (iPhone 5S) to post me a local notification on didEnterRegion: event.
When the app is in front, it starts ranging the beacon immediately in current region (if any) and updates happen in about one-second intervals.
When the app is in background, ranging is not enabled, otherwise it would immediately report that the beacon is gone (if you leave its range).
HOWEVER, It can really take up to 15 minutes (I've experienced this) for the device to post the didExitRegion: when in background in the worst case, when there is just significant location monitoring enabled combined with bad or no network. Otherwise it happens until about a minute.
Sorry, this didn't fit into a comment.

Resources