What you will learn

AdTag allows you to manage several notification options, such as the maximum number the SDK can display over a given period of time, or the minimum time span between two notifications (see our AdTag Application Settings document for more information. Depending on your objectives with beacons, you may want to add specific filters to refine the exact conditions around notification display in your app – for instance, to match notifications with specific user profiles, or to enable users to activate/deactivate specific types of notifications based on their personal preferences. This is what we call Custom Notification Strategies. This tutorial will guide through their creation & registration process with our SDK, and give you simple, practical illustrations to start working 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 notification creation tutorial and the introduction to notification strategies

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>6-Notification-Strategy>Starter project

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

Step 3: Create a Notification Strategy

  • Create a BeaconNotificationStrategyFilter class in the project
  • Open the BeaconNotificationStrategyFilter.h file
  • Import the ATLocationBeacon package

Switch to Swift

#import <ATLocationBeacon/ATLocationBeacon.h>
import ATLocationBeacon
  • The BeaconNotificationStrategyFilter.h must implement the ATBeaconNotificationStrategyDelegate delegate

Switch to Swift

@interface BeaconNotificationStrategyFilter : NSObject<ATBeaconNotificationStrategyDelegate>

@end
class BeaconNotificationStrategyFilter: NSObject, ATBeaconNotificationStrategyDelegate {
  • Open the BeaconNotificationStrategyFIlter.m file

  • Implement the methods of the ATBeaconNoficationStrategyDelegate

Switch to Swift

@implementation BeaconNotificationStrategyFilter

-(NSString *) getName {
    return nil;
}

-(void)updateParameters:(NSDictionary *) params {

}

-(bool) createNewNotification:(ATBeaconContent *)newBeaconContent feedStatus:(ATRangeFeedStatus)feedStatus{
    return false;
}

-(void) onNotificationIsCreated:(ATBeaconContent *)beconContent notificationStatus:(BOOL)notificationStatus{

}

-(bool) deleteCurrentNotification:(ATBeaconContent *)newBeaconContent feedStatus:(ATRangeFeedStatus)feedStatus{
    return false;
}

-(void) onNotificationIsDeleted:(ATBeaconContent *)beconContent notificationStatus:(BOOL)notificationStatus{}

-(void) onBackground{}

-(void) onForeground{}

-(void) onStartMonitoringRegion:(ATBeaconContent *)beaconContent feedStatus:(ATRangeFeedStatus)_feedStatus{}

-(void) load:(NSUserDefaults *)dataStore{}

-(void) save:(NSUserDefaults *)dataStore{}

@end
func getName() -> String! {
}

func updateParameters(_ params: [AnyHashable : Any]!) {
}

func createNewNotification(_ newBeaconContent: ATBeaconContent, feedStatus: ATRangeFeedStatus) -> Bool {
    return false
}

func deleteCurrentNotification(_ newBeaconContent: ATBeaconContent, feedStatus: ATRangeFeedStatus) -> Bool {
    return false
}

func onBackground() {

}

func onForeground() {

}

func onStartMonitoringRegion(_ beaconContent: ATBeaconContent, feedStatus: ATRangeFeedStatus) {

}

func save(_ dataStore: UserDefaults) {

}

func load(_ dataStore: UserDefaults) {

}

Step 4: Register the Notification Strategy

  • First, define the key of your custom strategy. For example:

Switch to Swift

-(NSString *) getName {
    return @"beaconNotificationStrategyFilter";
}
func getName() -> String! {
    return "beaconNotificationStrategyFilter"
}
  • Open the AppDelegate.m file
  • In the didFinishLaunchingWithOptions method, register the BeaconNotificationStrategyFilter

Switch to Swift

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
	[...]
    [self registerNotificationStrategy:[[BeaconNotificationStrategyFilter alloc] init]];
    [...]

    return YES;
}
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    registerNotificationStrategy(BeaconNotificationStrategyFilter())
}

Step 5: Experiment with the Custom Notification Strategy

  • Experiment with the default configuration: in the BeaconNotificationStrategyFilter.m file, the createNewNotification method returns false.

Switch to Swift

-(bool) createNewNotification:(ATBeaconContent *)newBeaconContent feedStatus:(ATRangeFeedStatus)feedStatus{
    return false;
}
func createNewNotification(_ newBeaconContent: ATBeaconContent, feedStatus: ATRangeFeedStatus) -> Bool {
    return false
}

Note:

This means that the Notification Strategy prevents the creation of any beacon notification.

  • You can launch the application to verify this, using the testing procedure described in the notification creation tutorial
  • Now, make the createNewNotification method return true:

Switch to Swift

-(bool) createNewNotification:(ATBeaconContent *)newBeaconContent feedStatus:(ATRangeFeedStatus)feedStatus{
    return true;
}
func createNewNotification(_ newBeaconContent: ATBeaconContent, feedStatus: ATRangeFeedStatus) -> Bool {
    return true
}

Note:

This means that the Notification Strategy authorizes the creation of all beacon notifications, without any filter.

  • Take a look at the deleteCurrentNotification method: it returns false

Switch to Swift

-(bool) deleteCurrentNotification:(ATBeaconContent *)newBeaconContent feedStatus:(ATRangeFeedStatus)feedStatus{
    return false;
}
func deleteCurrentNotification(_ newBeaconContent: ATBeaconContent, feedStatus: ATRangeFeedStatus) -> Bool {
    return false
}

Note:

This means that the beacon notification will not be cancelled when the mobile phone exits the beacon's range.
If the notification is not cancelled, the SDK cannot display a new beacon notification.

Therefore, in this example, only the first notification is displayed, and keeps being displayed until the user cancels it. If the user cancels the notification, no new beacon notification is displayed.

Step 6: Implement a real-life Custom Notification Strategy

Let’s continue the tutorial with the implementation of a Custom Notification Strategy that limits the number of notifications a user will see, by defining a minimum time span between two beacon notifications.

  • In the BeaconNotificationStrategyFilter.h file
    • add a minTimeBetweenNotification parameter
    • declare a constructor with a minTimeBetweenNotification parameter

Switch to Swift

@interface BeaconNotificationStrategyFilter : NSObject<ATBeaconNotificationStrategyDelegate>{
    double minTimeBetweenNotification;
}


-(id) initWithMinTimeBetweenNotification:(long)minTime;

@end
class BeaconNotificationFilter: NSObject, ATBeaconNotificationStrategyDelegate {
    var minTimeBetweenNotification : Double!

    convenience init(timeBetweenNotification: Int) {
    }
}
  • In the BeaconNotificationStrategyFilter.m file, implement the newly declared constructor

Switch to Swift

-(id) initWithMinTimeBetweenNotification:(long)minTime{
    self = [super init];
    if(self){
        minTimeBetweenNotification = (double) minTime / 1000.0;
    }
    return self;
}
convenience init(timeBetweenNotification: Int) {
    self.init()
    self.minTimeBetweenNotification = (Double(timeBetweenNotification) / 1000)
}
  • In the ApplicationDelegate.m file, update the BeaconNotificationStrategyFilter declaration, and set a time span of 5 minutes between each notification:

Switch to Swift

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [...]
    [self registerNotificationStrategy:[[BeaconNotificationStrategyFilter alloc] initWithMinTimeBetweenNotification: 5 * 60 * 1000]];
    [...]
}
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    [...]
    registerNotificationStrategy(BeaconNotificationFilter(timeBetweenNotification: 5 * 60 * 1000))
    [...]
}
  • Back in theBeaconNotificationStrategyFilter.h file, add a minNextTimeNotification parameter to define the next time that a beacon notification can be displayed.

Note:

The minNextTimeNotification is an essentiel parameter that must be saved and restored after an application is killed and restarted.

This can be achieved using the load and save methods.
The SDK calls these methods at the best time and uses a DataStore to save the data.

  • In the BeaconNotificationStrategyFilter.h file, create a static MIN_NEXT_TIME_NOTIFICATION, which will be used as a key to save and load the minNextTimeNotification data.

Switch to Swift

#define MIN_NEXT_TIME_NOTIFICATION @"com.notification.minNextTimeNotification"

@interface BeaconNotificationStrategyFilter : NSObject<ATBeaconNotificationStrategyDelegate>{
    double minTimeBetweenNotification;
    double minNextTimeNotification;
}
class BeaconNotificationFilter: NSObject, ATBeaconNotificationStrategyDelegate {
    var minTimeBetweenNotification : Double!
    var minNextTimeNotification : Double!

}

Note:

Make sure that you choose a key that is truly unique, because the DataStore is common to all notification strategies.

  • In the BeaconNotificationStrategyFilter.m, implement the save and load methods in order to save and load the minNextTimeNotification parameter

Switch to Swift

-(void) load:(NSUserDefaults *)dataStore{
    minNextTimeNotification = [dataStore doubleForKey:MIN_NEXT_TIME_NOTIFICATION];
}

-(void) save:(NSUserDefaults *)dataStore{
    [dataStore setDouble:minNextTimeNotification forKey:MIN_NEXT_TIME_NOTIFICATION];
}
func save(_ dataStore: UserDefaults) {
    dataStore.set(minNextTimeNotification, forKey: "com.notification.minNextTimeNotification")
}

func load(_ dataStore: UserDefaults) {
    minNextTimeNotification = dataStore.double(forKey: "com.notification.minNextTimeNotification")
}
  • In the createNewNotification method, use the minNextTimeNotification parameter to define when the SDK is authorized to notify/let the application create a notification.

Switch to Swift

-(bool) createNewNotification:(ATBeaconContent *)newBeaconContent feedStatus:(ATRangeFeedStatus)feedStatus{
    return minNextTimeNotification < CACurrentMediaTime();
}
func createNewNotification(_ newBeaconContent: ATBeaconContent, feedStatus: ATRangeFeedStatus) -> Bool {
    return self.minNextTimeNotification < CFAbsoluteTimeGetCurrent()
}
  • As the goal of this tutorial is only to limit the number of notifications a user can see, no change will be made to the default cancellation process. As such, the deleteCurrentNotification method must return true to let the SDK cancel the notification normally.

Switch to Swift

-(bool) deleteCurrentNotification:(ATBeaconContent *)newBeaconContent feedStatus:(ATRangeFeedStatus)feedStatus{
    return true;
}
func deleteCurrentNotification(_ newBeaconContent: ATBeaconContent, feedStatus: ATRangeFeedStatus) -> Bool {
    return true
}
  • Once the notification has been deleted, update the minNextTimeNotification parameter, in order to define when a new notification can be displayed

Switch to Swift

-(void) onNotificationIsDeleted:(ATBeaconContent *)beconContent notificationStatus:(BOOL)notificationStatus{
    if(notificationStatus){
        minNextTimeNotification = CACurrentMediaTime() + minTimeBetweenNotification;
    }
}
func onNotificationIsDeleted(_ beconContent: ATBeaconContent, notificationStatus: Bool) {
    if(notificationStatus){
        minNextTimeNotification = CACurrentMediaTime() + minTimeBetweenNotification;
    }
}

Note 1:

Keep in mind that even if the specific Notification Strategy that you have just implemented always deletes the notification, this is not necessarily the case for all of the Notification Strategies that will be added to your application.

Therefore:

  • do not update any parameters in the deleteCurrentNotification method, because other strategies may require that the notification stay, even when the phone exits the beacon's range
  • always do it through the onNotificationDeleted method after checking the deletion status

Similarly, do not use the createBeaconNotification method to update parameters, but always use the onCreateBeaconNotification after checking the creation status

Note 2:

The following methods allow you to update your notification strategy parameters for specific occasions:

  • onStartMonitoringRegion: when the SDK starts to monitor zone entries and exits for a specific beacon
  • onBackground: when the application switches from foreground to background
  • onForeground: when the application switches from background to foreground

Step 7: 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

  7. Wait for the notification to be cancelled

  8. Re-start your beacon

  9. Wait for 5 min and double-check that no notification appears