What you will learn

Herow allows you to manage several notification options, such as the maximum number of notifications the SDK can display over a given period of time, or the minimum time span between two notifications.

Depending on your objectives with zones, 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 Filters. 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

Step 1: Clone the sdk-tutorial repository

  • Clone the sdk-tutorial repository
git clone https://github.com/Connecthings/sdk-tutorial.git

objectivec

  • Open the ios>ObjectiveC>Zone>2-Notification>Starter folder

SWIFT

  • Open the ios>SWIFT>Zone>2-Notification>Starter folder

Step 2: Configure the SDK

  • Configure your CocoaPod files and .plist
  • Configure your SDK with:
    • the appropriate Herow Environment ( PREPROD / PROD )
    • your SDK credentials

Switch to Swift

[[[[HerowInitializer sharedInstance] configPlatform: HerowPlatform.prod]
									 configAppWithIdentifier:@"your username"
									 sdkKey:@"your SDK Key"]
									 synchronize];

herowInitializer = HerowInitializer.shared
herowInitializer?.configPlatform(Platform.prod)
				 .configApp(identifier: "your username", sdkKey: "your SDK Key")
				 .synchronize()

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

Step 3: Create a Notification Filter

Warnning:

In an Objective-C project, you must implements the NotificationFilter using swift.

  • Create a MyNotificationFilter swift class in the project
  • Open the MyNotificationFilter file
  • Import the ConnectPlaceCommon and ConnectPlaceActions package

Switch to Swift

import ConnectPlaceCommon
import ConnectPlaceActions
import ConnectPlaceCommon
import ConnectPlaceActions
  • The MyNotificationFilter file must extend the BaseNotificationFilter class

Switch to Swift

@objc
public class MyNotificationFilter: BaseNotificationFilter {
@objc
public class MyNotificationFilter: BaseNotificationFilter {
  • Open the MyNotificationFilter file
  • Override the methods of the BaseNotificationFilter

Switch to Swift

@objc
public class MyNotificationFilter: BaseNotificationFilter {
    public override func getName() -> String {
        return ""
    }

    public override func createNewNotification(placeNotification: PlaceNotification) -> Bool {
        return false
    }

    public override func deleteCurrentNotification(placeNotification: PlaceNotification?) -> Bool {
        return false
    }

    public override func onNotificationCreated(placeNotification: PlaceNotification, created: Bool) {

    }

    public override func onNotificationDeleted(placeNotification: PlaceNotification?, deleted: Bool) {

    }

    public override func onBackground() {

    }

    public override func onForeground() {

    }

    public override func load(holder: DataHolderUserDefaults) {

    }

    public override func save(holder: DataHolderUserDefaults) {

    }
}
@objc
public class MyNotificationFilter: BaseNotificationFilter {
    public override func getName() -> String {
        return ""
    }

    public override func createNewNotification(placeNotification: PlaceNotification) -> Bool {
        return false
    }

    public override func deleteCurrentNotification(placeNotification: PlaceNotification?) -> Bool {
        return false
    }

    public override func onNotificationCreated(placeNotification: PlaceNotification, created: Bool) {

    }

    public override func onNotificationDeleted(placeNotification: PlaceNotification?, deleted: Bool) {

    }

    public override func onBackground() {

    }

    public override func onForeground() {

    }

    public override func load(holder: DataHolderUserDefaults) {

    }

    public override func save(holder: DataHolderUserDefaults) {

    }

    public override func updateParameters(parameters: AnyObject) {

    }

    public func override reset() {

    }
}

Step 4: Register the Notification Filter

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

Switch to Swift

public func getName() -> String {
    return "MyNotificationFilter"
}
public func getName() -> String {
    return "MyNotificationFilter"
}
  • Open the AppDelegate.m file
  • In the didFinishLaunchingWithOptions method, register the MyNotificationFilter class

Switch to Swift

- (BOOL)application:(UIApplication *) application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [...]
    [[HerowDetectionManager shared] addNotificationFilter:[[MyNotificationFilter alloc] init]];
    [...]
}
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    [...]
    HerowDetectionManager.shared.addNotificationFilter(MyNotificationFilter())
    [...]
}

WARNING:

To be able to access your Swift class, if you have an Objective-C application, your project need to :

Step 5: Experiment with the Custom Notification Filter

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

Switch to Swift

public func createNewNotification(placeNotification: PlaceNotification) -> Bool {
    return false
}
public func createNewNotification(placeNotification: PlaceNotification) -> Bool {
    return false
}

Note:

This means that the Notification Filter prevents the creation of any 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

public func createNewNotification(placeNotification: PlaceNotification) -> Bool {
    return true
}
public func createNewNotification(placeNotification: PlaceNotification) -> Bool {
    return true
}

Note:

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

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

Switch to Swift

public func deleteCurrentNotification(placeNotification: PlaceNotification?) -> Bool {
    return false
}
public func deleteCurrentNotification(placeNotification: PlaceNotification?) -> Bool {
    return false
}

Note:

This means that the notification will not be cancelled when the mobile phone exits the zones. If the notification is not cancelled, the SDK cannot display a new 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 notification is displayed.

Step 6: Implement a real-life Custom Notification Strategy

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

  • In the MyNotificationFilter file
    • add a minTimeBetweenNotification parameter
    • declare a constructor with a minTimeBetweenNotification parameter

Switch to Swift

public class MyNotificationFilter: BaseNotificationFilter {
    let minTimeBetweenNotification : Double

    @objc
    public init(_ minTimeBetweenNotification: Double) {
    }
    [...]
}
public class MyNotificationFilter: BaseNotificationFilter {
    let minTimeBetweenNotification : Double

    @objc
    public init(_ minTimeBetweenNotification: Double) {
    }
    [...]
}
  • In the MyNotificationFilter file, implement the newly declared constructor

Switch to Swift

@objc
public init(_ minTimeBetweenNotification: Double) {
    self.minTimeBetweenNotification = minTimeBetweenNotification
}
@objc
public init(_ minTimeBetweenNotification: Double) {
    self.minTimeBetweenNotification = minTimeBetweenNotification
}
  • In the ApplicationDelegate file, update the MyNotificationFilter declaration, and set a time span of 5 minutes between each notification:

Switch to Swift

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [...]
    [[HerowDetectionManager shared] addNotificationFilter:[[MyNotificationFilter alloc] init:5 * 60]];
    [...]
}
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    [...]
    HerowDetectionManager.shared.addNotificationFilter(MyNotificationFilter(timeBetweenNotification:60 * 5))
    [...]
}
  • Back in the MyNotificationFilter file, add a minNextTimeNotification parameter to define the next time that a notification can be displayed.

Note:

The minNextTimeNotification is an essential 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 DataHolderUserDefaults to save the data. It's just a wrapper of the UserDefaults class.

  • In the MyNotificationFilter 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

@objc
public class MyNotificationFilter: BaseNotificationFilter {
    static let MIN_NEXT_TIME_NOTIFICATION: String = "com.notification.minNextTimeNotification"
    let minTimeBetweenNotification: Double
    var minNextTimeNotification: Double
    [...]
}
@objc
public class MyNotificationFilter: BaseNotificationFilter {
    static let MIN_NEXT_TIME_NOTIFICATION: String = "com.notification.minNextTimeNotification"
    let minTimeBetweenNotification: Double
    var minNextTimeNotification: Double
    [...]
}

Note:

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

  • In the NotificationFilter, implement the save and load methods in order to save and load the minNextTimeNotification parameter

Switch to Swift

override public func save(holder: DataHolderUserDefaults) {
    holder.putDouble(key: MyNotificationFilter.MIN_NEXT_TIME_NOTIFICATION, value: minNextTimeNotification)
}

override public func load(holder: DataHolderUserDefaults) {
    minNextTimeNotification = holder.getDouble(key: MyNotificationFilter.MIN_NEXT_TIME_NOTIFICATION)
}
override public func save(holder: DataHolderUserDefaults) {
    holder.putDouble(key: MyNotificationFilter.MIN_NEXT_TIME_NOTIFICATION, value: minNextTimeNotification)
}

override public func load(holder: DataHolderUserDefaults) {
    minNextTimeNotification = holder.getDouble(key: MyNotificationFilter.MIN_NEXT_TIME_NOTIFICATION)
}
  • 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

public override func createNewNotification(placeNotification: PlaceNotification) -> Bool {
    return self.minNextTimeNotification < CACurrentMediaTime()
}
public override func createNewNotification(placeNotification: PlaceNotification) -> Bool {
    return self.minNextTimeNotification < CACurrentMediaTime()
}
  • 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

public override func deleteCurrentNotification(placeNotification: PlaceNotification?) -> Bool {
    return true
}
public override func deleteCurrentNotification(placeNotification: PlaceNotification?) -> 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

public override func onNotificationDeleted(placeNotification: PlaceNotification?, deleted: Bool) {
    if (deleted) {
        minNextTimeNotification = CACurrentMediaTime() + minTimeBetweenNotification;
    }
}
public override func onNotificationDeleted(placeNotification: PlaceNotification?, deleted: Bool) {
    if (deleted) {
        minNextTimeNotification = CACurrentMediaTime() + minTimeBetweenNotification;
    }
}

Note 1:

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

Therefore:

  • do not update any parameters in the deleteCurrentNotification method, because other filters may require that the notification stays, even when the phone exits the zone’s range
  • always do it through the onNotificationDeleted method after checking the deletion status

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

Note 2:

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

  • onBackground: when the application switches from foreground to background
  • onForeground: when the application switches from background to foreground

Step 7: Start testing

Refer to our quick start tutorial to test the project