Time spend around a beacon - ios

What should be the correct approach to identify time spend around a beacon[not within a region] in background. I am able to do this when app is in foreground using didRangeBeacons and some business logic.I read on few forums that ranging does work when app has registered for location updates in background, but i am having no success. I have added the location updates key for UIBackgroundModes in plist.
I am using estimote beacons and their sdk.

I see two possible solutions here:
Listen for enter and exit region events, store the timestamps and then use them to calculate the time span on exit. If you define your region so that it encompasses only one beacon, monitoring the region will be equivalent to monitoring the beacon. The only thing to keep in mind is that iOS imposes a limit of 20 regions to be monitored at the same time - so this solution doesn't scale above 20 beacons.
Use ranging in the background. Apart from the UIBackgroundModes, you also need to start regular location services, i.e. startUpdatingLocation.
Beacon ranging delivers events normally while an app is running in the foreground. When your app is in the background, this service delivers events only when the location-updates background mode is enabled for the app and the standard location service is running.
(this is from CLLocationManager class reference, section "Using Location Services in the Background")
Note that ranging in the background will be draining the battery life more than usual, and Apple also requires justification for using the background modes. Unless there's some value for the user of your app coming from the background modes, they might choose to reject it. All in all, use the background ranging wisely! (:

Related

iOS: Location Update in Application Suspended State

Is it possible to update location when application is in suspended/terminate state.
i want to update location every 500 meters when app is in suspended/terminate state.
thanks in advance.
When terminated the only real way to get updates is to use Region Monitoring but you will only get major updates so I doubt it will work for 500 meters.
From the documentation:
If your app is terminated either by a user or by the system, the
system doesn't automatically restart your app when new location
updates arrive. A user must explicitly relaunch your app before the
delivery of location updates resumes. The only way to have your app
relaunched automatically is to use region monitoring or
significant-change location service. However, when a user disables the
Background App Refresh setting either globally or specifically for
your app, the system doesn't relaunch your app for any location
events, including significant change or region monitoring events.
Further, while Background App Refresh is off your app won't receive
significant change or region monitoring events even when it's in the
foreground.
There are good reasons for this. Firstly people don't want apps that 'snoop' on them all the time and even if there is a good reason imagine having 10 apps doing this constantly. It's going to start causing you performance and battery life issues.
EDIT
There appears to be some confusion by a lot of people over this issue so I will attempt to clear things up a bit.
Your app is NOT supposed to be continually tracking location while terminated (or suspended really). You are just not allowed to do this both for privacy reasons and so that you don't drain the battery excessively.
While your app is in the foreground you can use location services via startUpdatingLocation to monitor the device location. Assuming the app has been granted permission this will use all available hardware (GPS, WiFi, Cellular).
Now from the documentation itself:
If you start this service and your app is suspended, the system stops
the delivery of events until your app starts running again (either in
the foreground or background). If your app is terminated, the delivery
of new location events stops altogether. Therefore, if your app needs
to receive location events while in the background, it must include
the UIBackgroundModes key (with the location value) in its Info.plist
file.
So once suspended and terminated your options are really to monitor regions and to monitor for significant location changes. Neither of these are particularly accurate or frequent. One reason for this is that they only use low power methods to get the position (WiFi and Cellular) they don't use the GPS.
So no accurate and/or frequent location tracking while an app is suspended or terminated. This just has to be accepted and you need to design your apps accordingly.
let locationManager = CLLocationManager()
locationManager.startMonitoringSignificantLocationChanges()
After returning a current location fix, the receiver generates update events only when a significant change in the user’s location is detected. It does not rely on the value in the distanceFilter property to generate events
If you start this service and your app is subsequently terminated, the system automatically relaunches the app into the background if a new event arrives. In such a case, the options dictionary passed to the application(:willFinishLaunchingWithOptions:) and application(:didFinishLaunchingWithOptions:) methods of your app delegate contains the key location to indicate that your app was launched because of a location event. Upon relaunch, you must still configure a location manager object and call this method to continue receiving location events. When you restart location services, the current event is delivered to your delegate immediately. In addition, the location property of your location manager object is populated with the most recent location object even before you start location services.
Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
Hope It helps

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.

DidEnterRegion only called if requestAlwaysAuthorization is called. Beacons

didEnterRegion and didExitRegion are only called after I request and allow Always Authorization for CoreLocation
Even if I request WhenInUseAuthorization didExit and didEnter won't be called
How am I supposed to trigger ranging of beacons if I can't get this to be called?
Any solutions?
UPDATE
Apple rejected my app for calling requestAlwaysAuthorization()
Here is my question submitted to the review team this morning:
In order to monitor beacon regions (a very core functionality of beacons used in many apps including some Apple apps) you need to have the user allow the app to access location even when not using the app. I am using .requestAlwaysAuthorization to enable beacons to monitor in the background. Why won't this be allowed?
Apples response this afternoon on iTunes Connect:
Thank you for your feedback. However, background location is not necessary for iBeacon functionality. Therefore, it is necessary to remove the background location feature before resubmission.
So if beacons are supposed to automatically monitor regions in the background, but I can't ask permission for background monitoring and beacons won't monitor in the background unless I get permission, how then am I supposed to monitor regions in the background??
Do you mean when the app is in the background? If so, then it is true that didEnterRegion and didExitRegion don't get called with only a WhenInUseAuthorization. They will only get called when you app is in the foreground and you enter/exit a region
background location is not necessary for iBeacon functionality. Therefore, it is necessary to remove the background location feature before resubmission.
It seems that your app was rejected because of the Background Modes (specifically, the "location updates" mode), no the "always" authorization. You don't need any Background Modes enabled for beacon monitoring to work in the background, the "always" authorization is enough.
Simply disable the Background Modes capability in your project settings and you should be good!
Unfortunately, you must request Always Allow location access to use region monitoring with beacons.
From the docs:
Important
Apps must have always authorization to use region monitoring, and they must be configured with the Location updates background mode to be launched.
https://developer.apple.com/documentation/corelocation/determining_the_proximity_to_an_ibeacon

iOS : Region monitoring and battery usage

I would like to use region monitoring in iOS , for location based alerts/calculations.
I'm worried that it would drain the battery.
I searched for it on the iOS reference , and couldn't find any evidence for it.
Is that service available at all times , regardless of the region monitoring (i.e. scanned every minute or so...) or should I use the "significant location change" API instead ?
update : so , battery usage isn't dramatic. Its pretty good actually.
would like to receive some advice regarding switching between the modes (region/standard).
After checking for almost 2 weeks , I can tell that region monitoring does not significantly drain the battery.
As a matter of fact , it will be an active service in iOS 5 for sure , as the built-in reminders app will use region monitoring 24/7.
Region monitoring shouldn't have anywhere near the same affect on battery life as location tracking does.
According to Apple's developer documentation, region monitoring is built upon CoreLocation's "significant-change" location service. In order to conserve battery life, this service does not poll position information using aGPS, but instead simply tracks changes in the user's current cell tower.
Whenever the cell tower changes, iOS calculates whether any region boundaries were crossed. If a region crossing occurs while an iOS app is not running, iOS automatically wakes it up (or relaunches it) in the background so that it can process the event via the didEnterRegion:/didExitRegion: callbacks.

Resources