I know that the main purposes of the
-(void)locationManager:(CLLocationManager*)manager
didRangeBeacons:(NSArray*)beacons
inRegion:(CLBeaconRegion*)region
is to work while the app in foreground.
While in background,
- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion *)region
is used to detect beacons but with not as much information as wanted (minor and major ids from CLBeacons to provide contextual information).
I know that delegate methods from the CLLocationManager allow to run briefly code in background.
Is it possible to do something like that : - start briefly to range beacons in background when entering a region - call a webservice in background according to minor/major ids - dispatch UILocalNotification configured with the return result of the webservice
- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion *)region
{
if (![region isKindOfClass:[CLBeaconRegion class]]) return;
[locationManager startRangingBeaconsInRegion:(CLBeaconRegion*)region];
}
and then :
-(void)locationManager:(CLLocationManager*)manager
didRangeBeacons:(NSArray*)beacons
inRegion:(CLBeaconRegion*)region
{
if (beacons.count == 0) return;
CLBeacon *foundBeacon = [sortedBeacons firstObject];
// DO STUFF IN BACKGROUND
if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateActive){
//Call for a webservice according to minor /major
//Dispatch contextual notification
// ^success(...)
UILocalNotification * theNotification = [[UILocalNotification alloc] init];
theNotification.alertBody = [NSString stringWithFormat:@""];
theNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1];
[[UIApplication sharedApplication] scheduleLocalNotification:theNotification];
}
else{ //DO STUFF IN FOREGROUND
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"proximity"
ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"accuracy"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor,sortDescriptor2];
NSArray *sortedBeacons = [beacons sortedArrayUsingDescriptors:sortDescriptors];
//determine which beacon will be used to trigger foreground event
}
}
The maximum range of an iBeacon transmission will depend on the location and placement, obstructions in the environment and where the device is being stored (e.g. in a leather handbag or with a thick case). Standard beacons have an approximate range of 70 meters. Long range beacons can reach up to 450 meters.
To broadcast your beacon's identity from an iOS device, use the Core Bluetooth framework to configure the iOS device as a Bluetooth peripheral. When configured as a peripheral, your iOS device broadcasts its beacon information out to other devices using the Bluetooth hardware.
Beacons themselves don't collect any data. They do not send marketing messages to your phone. They broadcast location marks that your phone and apps using your phone can take advantage of to understand more precisely where you are.
Summary: For installations with regular beacons (an iBeacon is a type of beacon) then you cannot do much without an app, as you cannot interact with users (even after the additions from Eddystone).
I have experienced exactly same scenario. I have used below pattern:
// start background task
- (void)beginBackgroundTask {
if (self.backgroundTask != UIBackgroundTaskInvalid) {
[self endBackgroundTask];
}
self.backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundTask];
}];
}
// end background task
- (void)endBackgroundTask {
if (self.backgroundTask != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
}
self.backgroundTask = UIBackgroundTaskInvalid;
}
These are conventional methods I have used to mark/unmark background tasks like calling web service.
Here are some using patterns of these:
[self beginBackgroundTask];
[[MySessionManager sharedInstance] POST:MoteList parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
// process the response
[self endBackgroundTask];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
// error handling
}];
By the way, this background task time period is limited to 3mins around.
There are also another option to do background task for unlimited time period: That's to use multitasking API supported by NSURLSession since iOS 7. But it can be just used for download/upload tasks. If you need to do POST request, the server response should be downloadable json/xml data. The app should download that into a file and parse programmatically.
I hope this will help you.
Answering your original question: is it possible to range while in background mode? The answer is yes, but you should stop it as soon as possible. iOS will stop you anyway, but keeping the ranging on will drain battery and it won't make sense.
I have the same problem too.
My solution goes like this:
I know it sounds convoluted, and it is. It required in field testing to tune it. It satisfies the minimum requirement without depending on a fast internet connection.
I'll try the background tasks proposed by @ZhenHuiying, it sounds viable if the beacons are outdoors. In my case, the cell signal indoor is not reliable enough to show updated data while in background mode.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With