SDK

Device Registration

In this page you'll learn how device registration should be handled using Notificare's tvOS library. We'll dive deeper into all the functionality available for you in order to correctly manage devices in your app.

Please note that APNS will only work on a real device. There is also has a clear distinction between development and production servers. Whenever you debug your app from Xcode in a real device, your app will be using the development environment and whenever you archive your app for Adhoc, AppStore or Enterprise you will be using Production. This makes a difference when it comes to APNS since you will be getting two different identifiers for the same device.

Device registration should happen every time your app is launched. You also should never assume that the device token will never change, it does, and you should make sure you register the device every time that happens.

The simplest way to make sure this is done correctly is to request this registration every time after the onReady method has been triggered. In your AppDelegate.m or AppDelegate.swift, add the following to the onReady delegate method:

- (void)notificarePushLib:(NotificarePushLib *)library onReady:(NSDictionary *)info{
    [[NotificarePushLib shared] registerForNotifications];
}
func notificarePushLib(_ library: NotificarePushLib, onReady info: [AnyHashable : Any]) {
    NotificarePushLib.shared().registerForNotifications()
}

If everything is OK, invoking this method will request a device token from APNS which will trigger the following delegate method:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    [[NotificarePushLib shared] registerDevice:deviceToken completionHandler:^(NSDictionary *info) {

      //Device has been registered

    } errorHandler:^(NSError *error) {
        //Handle error
    }];
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    NotificarePushLib.shared().registerDevice(deviceToken, completionHandler: { (NSDictionary) -> Void in

        //Device has been registered

    }) { (NSError) -> Void in
        // handle error
    }
}

If your app does does not declare the necessary entitlements, it's not correctly provisioned or simply there was some other error while registering for notifications, the following delegate will be triggered instead:

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    //Handle error
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    //Handle error
}

At the same time if this is the first time you are requesting for push notifications, the user will also be prompted with a permission dialog requesting to show a badge. Even if the user denies it, you will still receive a device token which you can use to register in Notificare. If you do, the user will still be able to enjoy all the functionality available in Notificare, except we will not be able to show a badge in your application.

In tvOS your app can determine which kind of notification settings the user has authorized via the Notification Center object, as shown below:

[[[NotificarePushLib shared] notificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {

}];
NotificarePushLib.shared().notificationCenter.getNotificationSettings(completionHandler: { (UINotificationSettings) -> Void in

})

At this point your application should be able to handle anonymous device registrations but there is situations where you will want to register a device with a user profile. For example if you authenticate your users you will not want to register an anonymous device whenever the app launches. To handle this case you will want to change the way your app handles the device registration:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    if (MyUserClass.isLoggedIn) {

        [[NotificarePushLib shared] registerDevice:deviceToken withUserID:MyUserClass.userID withUsername:MyUserClass.userName completionHandler:^(NSDictionary * _Nonnull info) {

            //Device has been registered

        } errorHandler:^(NSError * _Nonnull error) {

            //Handle error
        }];

    } else {
        [[NotificarePushLib shared] registerDevice:deviceToken completionHandler:^(NSDictionary *info) {

          //Device has been registered
        } errorHandler:^(NSError *error) {

            //Handle error
        }];

    }

}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    if MyUserClass.isLoggedIn {

        NotificarePushLib.shared().registerDevice(deviceToken, withUserID: MyUserClass.userID, withUsername: MyUserClass.userName, completionHandler: { (NSDictionary) -> Void in

            //Handle Success

        }) { (NSError) -> Void in

            // handle Error
        }

    } else {

        NotificarePushLib.shared().registerDevice(deviceToken, completionHandler: { (NSDictionary) -> Void in

            //Handle Success
        }) { (NSError) -> Void in

            // handle Error
        }
    }

}

When you authenticate users, you will also have the need to do this device registration right after they login in your app. This can be done basically from any where in your app using the method below:

[[NotificarePushLib shared] registerDevice:deviceToken withUserID:MyUserClass.userID withUsername:MyUserClass.userName completionHandler:^(NSDictionary * _Nonnull info) {

    //Device has been registered

} errorHandler:^(NSError * _Nonnull error) {

    //Handle error
}];
NotificarePushLib.shared().registerDevice(deviceToken, withUserID: MyUserClass.userID, withUsername: MyUserClass.userName, completionHandler: { (NSDictionary) -> Void in

    //Handle Success

}) { (NSError) -> Void in

    // handle Error
}

You will also want to register users as anonymous once they sign out from your app. This can be done basically from anywhere in your app using the method below:

[[NotificarePushLib shared] registerDevice:deviceToken withUserID:nil withUsername:nil completionHandler:^(NSDictionary * _Nonnull info) {

    //Device has been registered

} errorHandler:^(NSError * _Nonnull error) {

    //Handle error
}];
NotificarePushLib.shared().registerDevice(deviceToken, withUserID: nil, withUsername: nil, completionHandler: { (NSDictionary) -> Void in

    //Handle Success

}) { (NSError) -> Void in

    // handle Error
}

User Data Fields

There are use cases where simply associating an userID and userName will not suffice. For those cases you can make use of User Data Fields where you can create key-value pairs for your application and then use them to extend your device registration. Before you can implement them you will need to first create them in your application via our dashboard. This is described here.

Once you have created one or more fields, you can implement this functionality in your app. To retrieve the list of fields allowed in your app you should use the following method:

- (void)notificarePushLib:(NotificarePushLib *)library onReady:(NSDictionary *)info{

    ...more code

    NSLog(@"%@", [[[NotificarePushLib shared] applicationInfo] objectForKey:@"userDataFields"]);
}
func notificarePushLib(_ library: NotificarePushLib, onReady info: [AnyHashable: Any]) {
    ...more code
    print("\(NotificarePushLib.shared().applicationInfo["userDataFields"])")
}

Then if you wish to retrieve the device's data for the allowed fields, you can use the example below:

[[NotificarePushLib shared] fetchUserData:^(NSDictionary * _Nonnull info) {

    for (NSDictionary * field in [[[NotificarePushLib shared] applicationInfo] objectForKey:@"userDataFields"]) {
        NSLog(@"%@", [[info objectForKey:@"userData"] objectForKey:[field objectForKey:@"key"]]);
    }

} errorHandler:^(NSError * _Nonnull error) {
    //Handle error
}];
NotificarePushLib.shared().fetchUserData({(_ info: [AnyHashable: Any]) -> Void in
    for field: [AnyHashable: Any] in NotificarePushLib.shared().applicationInfo["userDataFields"] {
        print("\(info["userData"][field["key"]])")
    }
}, errorHandler: {(_ error: Error?) -> Void in
    //Handle error
})

Whenever you want to update those fields with new values you should use the following method:

[[NotificarePushLib shared] updateUserData:@{@"firstName":@"John",@"lastName":@"Doe"} completionHandler:^(NSDictionary * _Nonnull info) {
    //Handle success
} errorHandler:^(NSError * _Nonnull error) {
    //Handle error
}];
NotificarePushLib.shared().updateUserData(["firstName": "John", "lastName": "Doe"], completionHandler: {(_ info: [AnyHashable: Any]) -> Void in
    //Handle success
}, errorHandler: {(_ error: Error?) -> Void in
    //Handle error
})

Do Not Disturb

Each device registered with Notificare can be configured to specify a period of time during the day where it should not receive notifications. You can use this functionality in your app settings view to allow the user to provide a time range where messages will not be displayed in the lock screen or notification center. Please note that if you are using our inbox functionality these message will still be there.

To retrieve a device's DnD preferences use the following method:

[[NotificarePushLib shared] fetchDoNotDisturb:^(NSDictionary *info) {

    if([info objectForKey:@"start"] && [info objectForKey:@"end"]){

        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"hh:mm"];
        NSString *startTime = [dateFormatter stringFromDate:[info objectForKey:@"start"]];
        NSString *endTime = [dateFormatter stringFromDate:[info objectForKey:@"end"]];

    }

} errorHandler:^(NSError *error) {
    //Handle error
}];
NotificarePushLib.shared().fetchDoNotDisturb({(_ info: [AnyHashable: Any]) -> Void in
    if info["start"] && info["end"] {
        var dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "hh:mm"
        var startTime: String = dateFormatter.string(from: info["start"] as? String ?? "")
        var endTime: String = dateFormatter.string(from: info["end"] as? String ?? "")
    }
}, errorHandler: {(_ error: Error?) -> Void in
    //Handle error
})

You can update the DnD values for a device, using the following method:

NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"hh:mm"];
NSDate *startTime = [dateFormat dateFromString:@"00:00"];
NSDate *endTime = [dateFormat dateFromString:@"08:00"];

[[NotificarePushLib shared] updateDoNotDisturb:startTime endTime:endTime completionHandler:^(NSDictionary *info) {
    //Handle success
} errorHandler:^(NSError *error) {
    //Handle error
}];
var dateFormat = DateFormatter()
dateFormat.dateFormat = "hh:mm"
var startTime: Date? = dateFormat.date(from: "00:00")
var endTime: Date? = dateFormat.date(from: "08:00")
NotificarePushLib.shared().updateDoNotDisturb(startTime, endTime: endTime, completionHandler: {(_ info: [AnyHashable: Any]) -> Void in
    //Handle success
}, errorHandler: {(_ error: Error?) -> Void in
    //Handle error
})

Disable Notifications

It is also possible to disabled notifications in APNS and unregister a device from Notificare. Although it is not a common use case, there might be situations where you want to implement this kind of functionality.

Pretty much the same way you register for notifications you will also unregister. To do that, use the following method:

[[NotificarePushLib shared] unregisterForNotifications];
NotificarePushLib.shared().unregisterForNotifications()

Doing this will remove the device token from APNS and deactivate the device in Notificare. This will also mean that all the messages in the device's inbox (if applicable), tags or any other device setting will be deleted too. If this is the user's only device, Notificare will also inactivate the user. Obviously after this you will not be able to find or send a message to this device.