Pushing notifications from iBeacon when the app is in the background or killed

Follow

One of the greatest features of iBeacon is that apps can be running in the background or even be killed (removed from the app switcher on iOS) and keep Monitoring for beacons.

Region Monitoring allows an app to determine when it enters and exits the range of a beacon region. To get a better grasp of how regions work, take a look at another article in our Knowledge Base: What is a beacon region?

Background Monitoring on iOS and Android

To make Monitoring work in the background on iOS, your app needs to request ‘always’ authorization for accessing Location Services. Learn about handling Location Services.

Remember that exiting a region has a built-in 30-second delay, to avoid false positives. During those 30 seconds, the app cannot receive any signal from the beacons in particular region to trigger an exit event. Also, when the phone is locked, Monitoring is less responsive, so both enter and exit events might launch with a delay. That’s because iOS reduces Bluetooth scanning frequency when the device is locked, to preserve the battery.

After an exit/enter event, the app is woken up and remains active for 10 seconds.

Background Monitoring on Android is described in a separate article:

How Monitoring in the background works on Android?

Monitoring when the app is killed (iOS only)

Even if the app is not running, location events (related to the beacons in this case) are handled the same way as any other app launching events. Every time a phone enters or exits a region while the app is terminated, it will be automatically launched.

application:didFinishLaunchingWithOptions: method (of AppDelegate class) is called with UIApplicationLaunchOptionsLocationKey key existing in launchOptions parameter.

When you verify this key exists (so location was the reason that your app was launched) you should create new instance of ESTBeaconManager class, set delegate to AppDelegate object (or any other object that is working as ESTBeaconManagerDelegate and was created before this event occurred) and start monitoring.

Region you are passing to the startMonitoringForRegion: method is not important, as ESTBeaconManager delegate will receive the most recent region information. You can just pick any of the ones your app registered in iOS. After Monitoring is revoked, app will automatically receive most recent entered/exited region event in beaconManager:didEnterRegion: or beaconManager:didExitRegion: method.

Sample code:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ 
  if([launchOptions objectForKey:@"UIApplicationLaunchOptionsLocationKey"])
  {
    self.beaconManager = [ESTBeaconManager new];
    self.beaconManager.delegate = self;
    // don't forget the NSLocationAlwaysUsageDescription in your Info.plist
    [self.beaconManager requestAlwaysAuthorization];
    [self.beaconManager startMonitoringForRegion:[[ESTBeaconRegion alloc]
                                                  initWithProximityUUID:ESTIMOTE_PROXIMITY_UUID
                                                  identifier:@"AppRegion"]];
  }
  return YES;
}

-(void)beaconManager:(ESTBeaconManager *)manager didEnterRegion:(ESTBeaconRegion *)region
{
  UILocalNotification *notification = [[UILocalNotification alloc] init];
  notification.alertBody = @"Enter region";
  notification.soundName = UILocalNotificationDefaultSoundName;

  [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}
 
-(void)beaconManager:(ESTBeaconManager *)manager didExitRegion:(ESTBeaconRegion *)region
{
  UILocalNotification *notification = [[UILocalNotification alloc] init];
  notification.alertBody = @"Exit region";
  notification.soundName = UILocalNotificationDefaultSoundName;
 
  [[UIApplication sharedApplication] presentLocalNotificationNow:notification];
}

Just like with background Monitoring, after an exit/enter event is triggered, the app is woken up and remains active for 10 seconds.

Ranging

Remember that Ranging, the method used for approximating distance from individual beacons, should be used in the foreground (when the app is active on screen). For more information, read the following articles:

Was this article helpful?
4 out of 4 found this helpful

37 Comment(s)

  • Avatar
    Arfeen Godil

    Does this still work if I close the app myself by double tapping on the home button and kill the app from the multitask menu?

  • Avatar
    Wojtek Borowicz

    Hi Arfeem,

    Yes, this tutorial explains launching notifications in that exact situation :)

    Cheers.

  • Avatar
    Sergio Alejandro Torres

    Hello, i am implementing this to get a local notification when the app is closed but how does it work? sometimes it trigger the notification and sometimes doesn't.
    I would like to know why does this happen?

  • Avatar
    Wojtek Borowicz

    Hi Sergio,

    Could you share more details? Please remember that after you leave the region, there's always 30 seconds delay implemented as a part of Core Location to avoid false positives. Also, depending on advertising interval settings, phone's probing and environmental factors, triggering enter/exit events might be slightly delayed.

    Cheers.

  • Avatar
    Sergio Alejandro Torres

    I figured out what was happening, i needed to leave the range from the beacon... i was trying moving the iphone from the beacon between 2 and 8 meters again and it was trigging the notification but when i moved more than 10 meters and got completely out of the range i got the notification.
    So the problem was that i wasn't actually leaving the range of the beacon.
    But now i have an other question... is there a way to configure range of the beacon to be less meters??

    Cheers.

  • Avatar
    Wojtek Borowicz

    Hi,

    Sure: use the Estimote app to adjust broadcasting power. The less powerful the signal, the shorter the range :)

    Cheers.

  • Avatar
    Matteo Giurdanella

    Hello, i'm using your beacon and SDK to create an application for IOS. I read this guide but i have a problem. I initialize the region with my proximityUUID and identifier, i call startMonitoringForRegion, i implement didEnterRegion and didExitRegion in appDelegate.m, but when the app is killed the notification not arrive. Is there other parameters or methods that i must call in the app?
    Also where the method didRangebeacons should be invoked? In appDelegate.m or also in other file.m? Finally there are different between IOS 7 and IOS 8, because i use IOS 7 at this moment. Thanks!

  • Avatar
    Piotr Krawiec

    Hey Matteo—did you follow the article to the note? It's important to have your startMonitoringForRegion inside the application: didFinishLaunchingWithOptions: method.

    Ranging only works in the foreground so you can put it wherever you want. App delegate might be a good choice if you ranging spans multiple View Controllers, otherwise the View Controller will be a good spot as well.

  • Avatar
    Stephen

    Hi Wojtek,

    I also cannot get the notification to work when the app is closed, whether in secure iBeacon mode or non-secure iBeacon mode. Is there any test Estimote app out there demonstrates this use case?

  • Avatar
    Wojtek Borowicz

    Hi Stephen,

    Could you share the code you're using? Thanks.

    Cheers.

  • Avatar
    Hans

    Hi Wojtek,

    I tried to replicate above code, but doesn't seems to be able to make it work. Do i need to add extra settings? i used examples code from Estimote and includes above code inside ESTAppDelegate.

    i added below code inside applicationDidFinishLaunchingWithOptions

    if([launchOptions objectForKey:@"UIApplicationLaunchOptionsLocationKey"])
    {
    self.beaconManager = [ESTBeaconManager new];
    self.beaconManager.delegate = self;
    [self.beaconManager startMonitoringForRegion:[[ESTBeaconRegion alloc]
    initWithProximityUUID:ESTIMOTE_PROXIMITY_UUID
    identifier:@"com.myidentifier.region"]];
    }

    and implemented 3 delegates below:

    1. beaconManager:(ESTBeaconManager *)manager didDetermineState:
    2. beaconManager:(ESTBeaconManager *)manager didEnterRegion:
    3. beaconManager:(ESTBeaconManager *)manager didExitRegion:

    i tried the notification demo and on background mode (lockscreen) and it is working. But i cannot make it work when the apps is killed (no local notification received).

    There is 1 thing that i noticed, the example code didn't include Location updates in the background modes capabilities. While other tutorials for iBeacon include it. Is it related?or is there anything i need to do? Thanks.

  • Avatar
    Stephen

    Did anyone seriously get their Estimote iBeacon to notify IN SECURE MODE AFTER THE APP IS KILLED? Or is this just a theological myth that this should work?

  • Avatar
    Stephen

    Hi Wojtek,

    Can an ios app really be notified after it is killed when in the vicinity of an estimote ibeacon in secure mode, with UUIDs changing?

  • Avatar
    Piotr Krawiec

    Hi Stephen,

    I'll try to get you a working code snippet that does that. Thank you for your patience!

  • Avatar
    Piotr Krawiec

    Here's the code I put into AppDelegate. The app was relaunched as expected, thought it seems that there's a bug in our SDK that prevents the very first enter or exit event from happening after the app gets relaunched. Subsequent events are coming in just fine.

    Please note that secure regions might be a little less responsive than their regular counterparts. The maximum delay I was able to observe was close to 1 minute, though mostly if was just around 10-30 seconds.

    let beaconManager = ESTBeaconManager()
    let region = ESTBeaconRegion(proximityUUID: NSUUID(UUIDString: "B9407F30-F5F8-466E-AFF9-25556B57FE6D"), major: 8049, minor: 58243, identifier: "ice", secured: true)
    
    func beaconManager(manager: ESTBeaconManager!, didEnterRegion region: ESTBeaconRegion!) {
        println("bm didEnterRegion, region = \(region.identifier)")
    
        let notification = UILocalNotification()
        notification.alertBody = "didEnterRegion: \(region.identifier)"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    }
    
    func beaconManager(manager: ESTBeaconManager!, didExitRegion region: ESTBeaconRegion!) {
        println("bm didExitRegion, region = \(region.identifier)")
    
        let notification = UILocalNotification()
        notification.alertBody = "didExitRegion: \(region.identifier)"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    }
    
    func beaconManager(manager: ESTBeaconManager!, didDetermineState state: CLRegionState, forRegion region: ESTBeaconRegion!) {
        println("bm didDetermineState, region = \(region.identifier), state = \(state.rawValue)")
    }
    
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        let notification = UILocalNotification()
        notification.alertBody = "app did finish launching"
        UIApplication.sharedApplication().presentLocalNotificationNow(notification)
    
        ESTBeaconManager.setupAppID("xxx", andAppToken: "xxx")
        beaconManager.requestAlwaysAuthorization()
        beaconManager.delegate = self
    
        beaconManager.startMonitoringForRegion(region)
        beaconManager.startRangingBeaconsInRegion(region)
    
        return true
    }
    
  • Avatar
    Piotr Krawiec

    @Hans: there was a [self.beaconManager requestAlwaysAuthorization]; line missing in the example code shown in the article. I just added it, feel free to alter your code and see if it helps.

  • Avatar
    Hans

    Hi Piotr,

    Thanks for the reply, i put the code like the sample code above and the app killed scenario is now working for static uuid.

    But for secure mode, when we entered the major and minor for the ibeacon, then killed the app and wait for a moment with another app to verify that the uuid is changed, then move away from the secure beacon, the app didn't notified the exit region. Any suggestion? do we need to add extra code to above code? like creating ESTBeaconRegion with secured flag on? or something else?

  • Avatar
    Piotr Krawiec

    Hi Hans,

    Thanks for raising this up. In my own tests I described above I did manage to discover a bug in our SDK that prevents the very first event from happening. This only affects the Secure UUID monitoring, and only after an app gets killed.

    In the scenario you described, this explains why the exit region event is not being delivered to the app, but any subsequent events should work just fine. Also, even though the first event doesn't happen, the app still gets relaunched--it's only the notification that is being lost in the process.

    I've already passed information about this bug to our engineers and we'll be working on addressing that in one of the upcoming SDK releases. Stay tuned!

  • Avatar
    sushma kalle

    Hi,

    Does Android 5.0 has this feature?

  • Avatar
    Wojtek Borowicz

    Hi Sushma,

    On Android 5.0 the app still has to be running in the background, but the background scanning was redesigned to greatly improve power efficiency.

    Cheers.

  • Avatar
    Sylvain BRIAT

    Hi, i'm new in ios and beacons development, so maybe my question will seem obvious... How does my iphone knows which app to launch when passing near one of my beacons ? Is there a kind of database in the phone which associates a proximity uuid and an installed app ? Thanks !

  • Avatar
    Piotr Krawiec

    Hi Sylvain,

    Yup, you got it right! When your app starts monitoring for a certain beacon region, iOS saves this information internally and later when it hears the beacon it knows which app to deliver the event to. And, if the app turns out not to be running at the time, it'll relaunch it into the background.

  • Avatar
    Kelvin

    Hi,

    1. One point to clarify is that when the secure beacon is detected and the mobile app has very poor connection or no 3G signal, the beacon will not trigger RegionDidEnter event right ? Since it is unable to obtain the 'real' UUID from estimote cloud or too slow in the context of poor 3G signal ?

    2. Do you have any recommendation to implement personalized notification to monitor more than 20 beacons given the limitation on 20 beacons monitoring. We have a user case that required to trigger background notification to users when unique beacon is detected.

    Many thanks,

  • Avatar
    Wojtek Borowicz

    Hi Kelvin,

    As for the first question: you're right. Network connection is required to be able to connect to Estimote Cloud and resolve Secure UUID. that's why it's a good idea to enable Wi-Fi in locations with beacons deployed.

    Regarding regions: you can have as many beacons as you want in a single region (https://community.estimote.com/hc/en-us/articles/203776266-What-is-a-beacon-region-). But if you want each region defined by UUID, Major, and Minor, then you're limited to 20 beacons at the same time. But you can switch the regions you're monitoring for based on additional logic: for example GPS data.

    Cheers.

  • Avatar
    Kelvin

    Hi Wojtek,

    Regarding regions, you are suggesting that we define a set of logic to trigger a set of regions with unique UUID for monitoring. Instead of having to monitor regions that might not logical given the user physical location ?

    One more question, if we turn on secure UUID, it means that when RegionDidEnter is triggered, ESTBeaconRegion object in that method will contain the 'real' UUID right ?

    Thanks again.

  • Avatar
    Wojtek Borowicz

    Hey there,

    1. Exactly. For example if you have 20 UUIDs in Los Angeles, and 20 in San Francisco, you can use GPS data to figure out that the user is in SF. Then you only need to be monitoring for the UUIDs there :)

    2. That's right, real UUID will be obtained.

    Cheers.

  • Avatar
    Kelvin

    Hi Wojtek,

    For item 2, do you know how long is the 'window' in second before RegionDidEnter event is killed.

    Thanks again.

  • Avatar
    Samuel Cox

    Could the same logic be applied to give a notification when the accelerometer (movement of the estimote) has happened?

  • Avatar
    Wojtek Borowicz
  • Avatar
    Manu Jose

    Is it necessary to create new instance of ESTBeaconManager class in AppDelegate to receive enterRegion and exitRegion Notifications..?

    If we do so,we will have two instance of ESTBeaconManager class and both will receive the enterRegion and exitRegion Notification in their corrosponding delegate.

    I used only one instance of ESTBeaconManager class and monitored 3 regions in AppDelegate. I got notifications even after the app is killed , But after few seconds i got notifications for enterRegion and exitRegion continuesly even though the app/device is inside the range;.

Estimote is
hiring!