What you will learn:

By integrating our SDK, you can display Beacon Notifications on your app when a beacon is detected nearby.

To make things easier, our SDK contains a default Auto Beacon Notification: this is a built-in notification that is automatically generated when a beacon is detected nearby, as soon as the SDK has been initialized in your app.

You also have the ability to configure custom-built notifications, using our model of interfaces and built-in objects.

In both cases, you can manage the content of your beacon notifications directly on our AdTag platform.

This tutorial tells you more about these Auto and custom-built beacon notifications, and how you can work with them.

Pre-requisites - What you need to get started

  • Your SDK credentials, including an SDK Login, Password, and Company Key to initialize the SDK.
  • A BLE beacon, which has been configured on your account, in order to test interactions with your app.
  • An iOS Device, with Bluetooth 4.0 and iOs 8 and above.
  • The Xcode application, which you can download from the App store.
  • You must have completed the 5 minutes QuickStart Tutorial.

Initialize the SDK

Step 1: Clone the sdk-tutorial repository

  • Clone the sdk-tutorial repository
git clone https://github.com/Connecthings/sdk-tutorial.git
  • Open the iOs>beacon>2-Notification>Notification-Starter folder

Step 2: Configure the SDK

  • Configure your CocoaPod files and .plist
  • Configure your SDK with:
    • the UUID of your beacon
    • the appropriate Adtag Environment (DEMO / PREPROD / PROD / PROD_US)
    • your SDK credentials

Switch to Swift

[[[ATAdtagInitializer sharedInstance] configureUrlType:ATUrlTypeProd
                                              andLogin:@"__USER__" 
                                           andPassword:@"__PSWD__" 
                                            andCompany:@"__COMPANY__"] 
                                           synchronize];
ATAdtagInitializer.sharedInstance().configureUrlType(__UrlType__, 
                                            andLogin: "__USER__", 
                                         andPassword: "__PSWD__", 
                                          andCompany: "__COMPANY__")
                                   .synchronize();

If you need more informations, have a look to the 5 minutes quickstart tutorial

Enable your app to receive local beacon Notifications

Step 1: Register your application on the Notification Center

  • Open the AppDelegate.m file
  • For iOS 9 or below: in the didFinishLaunchingWithOptions method, register your application on the notification center:

Switch to Swift

-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    [...]
    if (SYSTEM_VERSION_LESS_THAN(@"10.0") && [application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
        [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];
    }
    return YES;
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    [...]
    if #available(iOS 10.0, *) {
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
            // Enable or disable features based on authorization.
        }
        let setting = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        UIApplication.shared.registerUserNotificationSettings(setting)
        UIApplication.shared.registerForRemoteNotifications()
    } else {
        if(UIApplication.instancesRespond(to: #selector(UIApplication.registerUserNotificationSettings(_:)))){
            let notificationCategory:UIMutableUserNotificationCategory = UIMutableUserNotificationCategory()
            notificationCategory.identifier = "INVITE_CATEGORY"
            //registerting for the notification.
            UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings (types: [.alert, .badge, .sound], categories: nil))
        }
    }
    return true
}
  • Open the ViewControllerBeacon.m file
  • For iOS 10 and above: in the viewDidLoad method, register the application on the notification center
- (void)viewDidLoad {
    [super viewDidLoad];
    [...]
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert)
                              completionHandler:^(BOOL granted, NSError * _Nullable error) {
                                  if (!error) {
                                      NSLog(@"request authorization succeeded!");
                                  }
                              }];
    }

}

Note 1:

On iOS 8 and above, you must register your application on the notification center, even if you are only using local notifications.

Note 2:

With iOs 10, Apple has introduced a new way of managing registration with the UNUserNotificationCenter.

Apple recommends to use it, but it is not mandatory.

For instance, an application that is registered on the notification center using the old code style will still be able to display notifications with pictures, generated with the new UNMutableNotificationContent.

Step 2: Override the applicationDidBeaconActive method

  • Explicitly implement the applicationDidBecomeActive method in the AppDelegate.m file.

Switch to Swift

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [super applicationDidBecomeActive:application];
}
override func applicationDidBecomeActive(_ application: UIApplication) {
    super.applicationDidBecomeActive(application);
}

Warning 1:

If the AppDelegate class does not explicitly call the super applicationDidBecomeActive method, the beacons won't be detected when your application is running in the background.

Warning 2:

The ATBeaconApDelegate class implements several methods of the UIApplicationDelegate.

Always call the super method when implementing a method from the UIApplicationDelegate, to ensure that you do not override its SDK implementation.

Step 3: Generate Beacon Notification analytics

  • Open the AppDelegate.m file
  • Override the didReceiveLocalNotification method and call the super method:

Switch to Swift

-(void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
    [super application:application didReceiveLocalNotification:notification];
}
override func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
    super.application(application, didReceive: notification);
}

Note:

The super method calls the didReceiveLocalNotification method from the ATBeaconManager, which allows your app:

  • to generate analytics associated with your beacon notifications and welcome notifications
  • to call the didReceiveNotificationContentReceived method of the ATBeaconReceiveNotificatonContentDelegate when necessary
  • to call the didReceiveWelcomeNotificationContentReceived method of the ATBeaconReceiveNotificatonContentDelegate when necessary (see next step)

If you cannot use the ATBeaconAppDelegate, you can call that same didReceiveLocalNotification method as follows:

[[ATBeaconManager sharedInstance] didReceiveLocalNotification:notification];

Step 4: Open a ViewController associated with a Beacon Notification

  • Open the AppDelegate.h file

  • Add the ATBeaconReceiveNotificatonContentDelegate to the AppDelegate, to allow your app to be notified when a user clicks on a local beacon notification

Switch to Swift

@interface AppDelegate : ATBeaconAppDelegate <UIApplicationDelegate,ATBeaconReceiveNotificatonContentDelegate>
class AppDelegate: ATBeaconAppDelegate, UIApplicationDelegate, ATBeaconReceiveNotificatonContentDelegate {

Note 1:

If your AppDelegate extends the ATBeaconAppDelegate, the ATBeaconReceiveNotificatonContentDelegate is registered automatically on the ATBeaconManager.

Otherwise, you must:

  • Register the delegate using:
[[ATBeaconManager sharedInstance] registerNotificationContentDelegate:YourDelegate];
  • Allow the ATBeaconManager to receive location notification events, by extending the didReceiveLocalNotification of your AppDelegate with the following code:
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{
   [adtagBeaconManager didReceiveLocalNotification:notification];
}
  • Implement the didReceiveBeaconNotification method of the ATBeaconReceiveNotificatonContentDelegate

Switch to Swift

-(void)didReceiveBeaconNotification:(ATBeaconContent *)_beaconContent {
    //Open the view controller associated with the notification
    //You can use [_beaconContent getUri] to match with a deeplink
    //Here is a simple example
    NSDictionary* dict = [NSDictionary dictionaryWithObject: _beaconContent forKey:@"beaconContent"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"BeaconNotification" object:nil userInfo:dict];
}
public func didReceiveBeaconNotification(_ _beaconContent: ATBeaconContent!){
    let beaconContentUserInfo:[String: ATBeaconContent] = ["beaconContent": _beaconContent]
    NotificationCenter.default.post(name: NSNotification.Name("beaconNotification"), object:nil, userInfo: beaconContentUserInfo)
}

Note 2:

This method is called when users click on a notification, to open the ViewController associated with the ATBeaconNotification

If your application uses deep links, you can use the [BeaconContent getUri] method to retrieve the deep link associated with the notification.

Customize your Auto Beacon Notifications

As a reminder, Auto Beacon Notifications are notifications generated by default by the SDK. You can manage their content (text – title & description - , URI, and content image), and disable them if necessary, directly from the AdTag platform, in the Application Management section.

Learn more on notification management in AdTag in the AdTag tutorial

Create custom-built notifications

If you would like to implement notifications that are more customizable than our Auto Beacon notifications, you can replace them with your own, custom-built, beacon notifications, as described in the following section.

Notification Model Overview

First, let’s go through an overview of the notification model, with the corresponding interfaces and built-in objects.

The ATAsyncBeaconNotificationDelegate

The ATAsyncBeaconNotificationDelegate is an interface that:

  • alerts your application when it has to create a beacon notification, using the createBeaconNotification method.
  • allows your application to complete an asynchronous task of your choice before displaying a notification.

The createBeaconNotification method has two arguments:

  • ATBeaconContent: the content to create the notifications.
  • ATAsyncBeaconNotificationManager: the object used to notify the SDK when the notification is ready to be displayed.

The ATAsyncBeaconNotificationManager

The ATAsyncBeaconNotificationManager is an interface that is mainly in charge of displaying the notification linked to a beacon. Before a notification is triggered, the ATAsyncBeaconNotificationManager checks that the corresponding beacon is still within range. If so, the notification is displayed; otherwise, nothing is displayed for the end user.

To notify the ATAsyncBeaconNotificationManager of the need to display a notification, you must call the displayBeaconNotification method.

The displayBeaconNotification method has two arguments:

  • ATBeaconContent: the content used to create the notification.
  • Notification: the notification that will be displayed, which can either be an UNMutableNotificationContent or an UILocalNotification object.

The AsyncBeaconNotificationImageCreator

The ATAsyncBeaconNotificationImageCreator is a specific implementation of the ATAsyncBeaconNotificationDelegate interface. It directly downloads the notification image from ADTAG, and display the beacon notification with the corresponding image for iOs 10 and above.

The ATAsyncBeaconNotificationImageCreator must be initialized with an ATBeaconNotificationImageBuilderDelegate.

The ATBeaconNotificationImageBuilderDelegate

The ATBeaconNotificationImageBuilderDelegate interface allows to create native Notifications once images are downloaded from ADTAG by the SDK.

It must implement the buildBeaconNotification method, which has two arguments:

  • ATBeaconContent: content used to create the notification
  • urlImage: local URL of the AdTag image used in the notification attachment. It can be nil.

This method must return a UILocalNotification or an UNMutableNotificationContent.

Note:

You have two options to customize your beacon notifications:

  • Option 1: you can use our pre-built BeaconNotificationImageCreator, to simply customize your notifications with images
  • Option 2: or you can implement your own AsyncBeaconNotificationListener for wider customization abilities

Option 1 is the simpler of the two; option 2 is great if you need to implement your own async tasks.

Option 1 will be explored in the following step. If you are interested in option 2, you can find a basic implementation of the AsyncBeaconNotificationListener inside the notification demo code folder.

Step 1: Create your own ATBeaconNotificationImageBuilderDelegate

  • Create a new class named MyBeaconNotificationBuilder
  • In the MyBeaconNotificationBuilder.h file:
    • Import the ATLocationBeacon
    • Implement the ATBeaconNotificationImageBuilderDelegate

Switch to Swift

#import <Foundation/Foundation.h>
#import <ATLocationBeacon/ATLocationBeacon.h>

@interface MyBeaconNotificationBuilder : NSObject <ATBeaconNotificationImageBuilderDelegate>

@end
import Foundation
import ATLocationBeacon

class MyBeaconNotificationBuilder : NSObject, ATBeaconNotificationImageBuilderDelegate {

}
  • Declare the buildBeaconNotification method in the MyBeaconNotificationBuilder.m file

Switch to Swift

@implementation MyBeaconNotificationBuilder

-(NSObject *) createBeaconNotification:(ATBeaconContent *) content andImageUrl:(NSURL *)imageUrl{
    
}

@end
func createBeaconNotification(_ content: ATBeaconContent!, andImageUrl imageUrl: URL!) -> NSObject! {

}

Step 2: Generate the local notification

  • Enable your app to create the appropriate notification based on the user’s iOS version

Switch to Swift

-(NSObject *) createBeaconNotification:(ATBeaconContent *) content andImageUrl:(NSURL *)imageUrl{
    NSDictionary *infoDict = [NSDictionary dictionaryWithObject:[content toJSONString] forKey:KEY_NOTIFICATION_CONTENT];
    
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
        UNMutableNotificationContent *notificationContent = [[UNMutableNotificationContent alloc] init];
        if([content isNotificationDescriptionEmpty]){
            notificationContent.body = [content getNotificationTitle];
        }else{
            notificationContent.body = [content getNotificationDescription];
        }
        if(![content isNotificationTitleEmpty]){
            notificationContent.title = [content getNotificationTitle];
        }
        notificationContent.userInfo = infoDict;
        if(imageUrl){
            UNNotificationAttachment *attachement1 = [UNNotificationAttachment attachmentWithIdentifier:@"com.connecthings.beaconNotificationImage" URL:imageUrl options:nil error:nil];
            notificationContent.attachments=@[attachement1];
        }
        return notificationContent;
    }else{
        ILog(@"create notification from app delegate");
        UILocalNotification *notification = [[UILocalNotification alloc]init];
        if([content isNotificationDescriptionEmpty]){
            [notification setAlertBody:[content getNotificationTitle]];
        }else{
            [notification setAlertBody:[content getNotificationDescription]];
        }
        
        if(SYSTEM_VERSION_GREATER_THAN(@"7.99") && ![content isNotificationTitleEmpty]){
            [notification setAlertTitle:[content getNotificationTitle]];
        }
        
        [notification setUserInfo:infoDict];
        return notification;
    }
}
func createBeaconNotification(_ content: ATBeaconContent!, andImageUrl imageUrl: URL!) -> NSObject! {
    let infoDict = [ KEY_NOTIFICATION_CONTENT : content.toJSONString() ]
    if #available(iOS 10.0, *) {
        let notificationContent:UNMutableNotificationContent! = UNMutableNotificationContent()
        notificationContent.title = content.getNotificationTitle()
        if content.isNotificationDescriptionEmpty() {
            notificationContent.body = content.getNotificationTitle()
        } else{
            notificationContent.body = content.getNotificationDescription()
        }
        if imageUrl != nil {
            do{
                let attachement:UNNotificationAttachment! = try UNNotificationAttachment.init(identifier: "com.connecthings.beacon.image", url: imageUrl, options: nil)
                 notificationContent.attachments = [attachement]
            }catch _{}
        }
        notificationContent.userInfo = infoDict
        return notificationContent;
    } else{
        let kLocalNotificationMessage:String! = content.getNotificationDescription()
        let kLocalNotificationTitle:String! = content.getNotificationTitle()
        let localNotification:UILocalNotification = UILocalNotification()
        
        localNotification.alertTitle = kLocalNotificationTitle
        if kLocalNotificationMessage?.isEmpty == false {
            localNotification.alertBody = kLocalNotificationTitle
        } else {
            localNotification.alertBody = kLocalNotificationMessage
        }
        localNotification.userInfo = infoDict
        return localNotification;
    }
}

Note 1:

The BeaconContent object contains the content associated with the beacon in Adtag. Two methods are available to retrieve the default content of a notification:

  • getNotificationTitle: retrieves the title of the notification
  • getNotificationDescription: retrieves the description of the notification

You can also base the text of your notifications on other ADTAG categories & fields of your choice, using the method getValueFromCategory. For example: BeaconContent getValueFromCategory:@"LINE" andField:@"DIRECTION" allows to retrieve the DIRECTION field of the LINE category for a real-time transit schedule use case.

Note 2:

The ATBeaconContent is saved as a JSON String in the NSDictionnary associated with the notification. NSDictionary *infoDict = [NSDictionary dictionaryWithObject:[content toJSONString] forKey:KEY_NOTIFICATION_CONTENT];
This allows the SDK to generate analytics, and enables you to easily get the ATBeaconContent associated with the notification.

Step 3: Register your ATAsyncBeaconNotificationDelegate

  • Open the AppDelegate.m file
  • Register ATAsyncBeaconNotificationImageCreator with a MyBeaconNoficationBuilder.

Switch to Swift

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [...]
    
    [self registerAsyncBeaconNotificationDelegate:[[ATAsyncBeaconNotificationImageCreator alloc] initWithBeaconNotificationBuilder:[[MyBeaconNotificationBuilder alloc] init]]];
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    [...]
    register(ATAsyncBeaconNotificationImageCreator.init(beaconNotificationBuilder:MyBeaconNotificationBuilder.init()))
    [...]
}

Note:

If your AppDelegate does not extend the ATBeaconAppDelegate, you can use:

[[ATBeaconManager sharedInstance] registerAsyncBeaconNotificationDelegate:[[ATAsyncBeaconNotificationImageCreator alloc] initWithBeaconNotificationBuilder:[[MyBeaconNotificationBuilder alloc] init]]];

Start testing

If your beacon is already emitting, you must stop/restart the emission process in order to simulate a new entry region for your smartphone, and generate a notification.

There are 2 solutions to stop/restart the emission process:

  • You can put the beacon inside a microwave (but don't start it!)
  • You can remove the battery from the beacon (in that case, depending on the model, it can take up to 30 seconds for the beacon to start emitting again after you reinsert the battery)
  1. In Xcode, click on "Play" to launch the installation of the application you have just built on your phone

  2. When the application starts, popups ask for permission to access your phone location, Bluetooth & notifications: grant them!

  3. Close your application or leave it running in the background

  4. Remove the beacon from the microwave or reinsert the battery

  5. Wait for a few seconds (maximum 1 minute)

  6. Click on the notification that has appeared on your screen just for fun