Start ranging beacons when app in background

Hi. I am creating an iOS app that is listening for a lot (more than 20) of beacons. I am monitoring a single region, with my own UUID in all the beacons. All the beacons have information added to them in a backend system, and are unique by the UUID, major and minor. So when the app enters the region, I need to start ranging to find the major and minor of the beacon, and fetch data from the back end.

I understand that iOS gives me about 5 seconds to range for beacons when the app is in the background. This is probably enough in most cases. But I`ve read some places that I can start a background task to get more time (3 minutes?).

What is the correct syntax/way of starting such a background task in iOS and Obj-C? At the moment I do this:

- (void)beaconManager:(id)manager didEnterRegion:(CLBeaconRegion *)region
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self.beaconManager startRangingBeaconsInRegion:self.region1];
    });
}

- (void)beaconManager:(id)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        if (beacons == nil || beacons.count == 0) return;
        CLBeacon *nearestBeacon = beacons[0];
..................................
    });
}

Is this dispatch_async giving me more time for ranging in the background?

Actually, it’s UIApplication’s beginBackgroundTaskWithExpirationHandler:

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/index.html#//apple_ref/occ/instm/UIApplication/beginBackgroundTaskWithExpirationHandler:

Yeah, I`ve seen that around. But not found any good examples with Estimote and iBeacons.

However, I finally found this one: http://developer.radiusnetworks.com/2014/11/13/extending-background-ranging-on-ios.html

Hope that does the trick :slight_smile:

1 Like

I`ve gotten this all to work now, but I have a related question as well.

It seems to the that when iOS gets the signal from my beacons, it can take a quite random amount of time before iOS actually bothers to call my didEnterRegion in my app?

If the app is open, or just recently put to the background, didEnterRegion seems to be called very fast, but if the app has been inactive for a long time (e.g. a day or so), and i enter a region, it can take up to a minute before didEnterRegion is called. At that time i start ranging for beacons nearby, but since i entered the region a minute ago, there might not be any beacons nearby anylonger to range for.

Can anyone confirm that this is a problem with iOS? And does anyone have any solutions for this?

Yes, that’s something we’ve seen many times over. Our hypothesis is that when the app has been inactive for a while, iOS switches the BLE scanning to some low power mode, which is also less responsive. Haven’t found any good workaround for that yet—I wonder if having a regular CLCircularRegion monitoring in place, basically a geofence around the venue where beacons are deployed, would help. iOS could then wake up the app before it encounters any beacons, and maybe that would bring the beacon monitoring back to the desired responsiveness.