Initializing APNs

This topic explains the details of the initialization process implemented in Implement Your Application of the push notification tutorial and how to add the actionable notification as below:

The push notification tutorial explains how to initialize the push notification feature in the topic for program implementation and the code corresponds to that shown in Initializing the simple push notification. If you use the code in the tutorial as it is for your mobile app, you do not need to implement the process described in this topic separately. Use this topic as a reference for implementing the actionable notification.

Initializing the simple push notification

In the tutorial, the application(_:didFinishLaunchingWithOptions:) method of the AppDelegate class initializes push notification as below:

Swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  // Initialize the Kii Cloud SDK.
  Kii.begin(withID: "___APPID___", andKey: "___APPID___", andSite: .JP)

  // Register the device to APNs.
  if #available(iOS 10, *) {
    // For iOS 10
    UNUserNotificationCenter.current().requestAuthorization(options:[.alert, .sound, .badge]) { (granted: Bool, error: Error?) in
      if (error != nil) {
        print("Failed to request authorization.")
        return
      }
      if granted {
        application.registerForRemoteNotifications()
      } else {
        print("The user refused the push notification.")
      }
    }
  } else {
    // For iOS 8/iOS 9
    let notificationSettings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
    application.registerUserNotificationSettings(notificationSettings)
    application.registerForRemoteNotifications()
  }

  return true
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
  print("Failed to register to APNs: \(error)")
}

Objective-C:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Initialize the Kii Cloud SDK.
  [Kii beginWithID:@"___APPID___"
            andKey:@"___APPKEY___"
           andSite:kiiSiteJP];

  // Register the device to APNs.
  if ([[UNUserNotificationCenter class] respondsToSelector:@selector(currentNotificationCenter)]) {
    // For iOS 10
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge)
                          completionHandler:^(BOOL granted, NSError * _Nullable error) {
      if (error != nil) {
        NSLog(@"Failed to request authorization.");
        return;
      }
      if (granted) {
        [application registerForRemoteNotifications];
      } else {
        NSLog(@"The user refused the push notification.");
      }
    }];
  } else {
    // For iOS 8/iOS 9
    UIUserNotificationSettings* notificationSettings =
        [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert |
                                                     UIUserNotificationTypeSound |
                                                     UIUserNotificationTypeBadge
                                          categories:nil];
    [application registerUserNotificationSettings:notificationSettings];
    [application registerForRemoteNotifications];
  }

  return YES;
}

- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
  NSLog(@"Failed to register to APNs: (%@)", error);
  // Handle the error.
}

As mentioned in the tutorial, the above code asks the user for permission to enable the push notification feature and registers the device to APNs. As a result, the application(_:didRegisterForRemoteNotificationsWithDeviceToken:) method can receive an APNs device token as explained in Installing a Device.

If the initialization of the push notification feature fails, the application(_:didFailToRegisterForRemoteNotificationsWithError:) method returns error.

Initializing the actionable notification

You can use various APIs related to the iOS push notification feature in the initialization code. This section describes how to initialize the feature for actionable notifications.

Notification actions are the buttons displayed when iOS receives a push notification (like the one shown below). The user can select an action to directly react to the push notification message in Notification Center or on the lock screen.

The setting by the user on the "Settings" screen of iOS determines if notification actions are shown in a banner or a dialog, or not shown at all. Actions can be also shown in Notification Center and the lock screen. Up to two actions can be shown in a banner and in Notification Center and up to four actions can be shown in a dialog.

The same numbers of actions can be shown on the lock screen. Additionally, you can program if the action requires a valid passcode on the lock screen.

You can define multiple sets of notification actions in one mobile app. iOS determines which notification action set to use by checking the category specified in the push message.

You need to define categories together with the associated notification actions and set their category identifiers when you initialize your mobile app. When the user selects a notification action on the screen, a set of the category identifier and the identifier of the selected action is passed to the mobile app. By checking these identifiers, the mobile app can take appropriate actions.

The following figure illustrates how the category and notification actions work:

  1. Register categories and notification actions when initializing the mobile app. Let us assume that we define two categories (CONTACT_CATEGORY and MESSAGE_CATEGORY) and define the notification actions as shown in the figure.

  2. Now suppose we get a push message with the body "You've received a request to add the contact." and the category CONTACT_CATEGORY.

  3. iOS reads the category in the push message and presents buttons "Ignore", "Accept" and "Block" that are associated with the category CONTACT_CATEGORY together with the message body. If the message is shown in a style other than dialog, only two buttons are shown.

  4. Now let us suppose that a user taps the "Accept" button. The mobile app's notification method will receive the category identifier CONTACT_CATEGORY and the action identifier ACCEPT_IDENTIFIER together with the push message body.

Sample code

The sample code below defines two custom notification actions, Accept and Decline, then assign them to a category, MESSAGE_CATEGORY.

You can customize the initialization process according to the specification of iOS as all the APIs used in this sample code are iOS APIs except for the one for initializing the Kii Cloud SDK. For more information about available options for the iOS push notification feature, refer to the iOS documentation and general technical information on the Internet. Those options are not part of the Kii Cloud technology.

Swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  // Initialize the Kii Cloud SDK.
  Kii.begin(withID: "___APPID___", andKey: "___APPID___", andSite: .JP)

  // Register the device to APNs.
  if #available(iOS 10, *) {
    // For iOS 10
    let acceptAction = UNNotificationAction(identifier: "ACCEPT_IDENTIFIER",
                                            title: "Accept",
                                            options: [])
    let declineAction = UNNotificationAction(identifier: "DECLINE_IDENTIFIER",
                                             title: "Decline",
                                             options: [.destructive])    // This action will appear in red.
    let category = UNNotificationCategory(identifier: "MESSAGE_CATEGORY",
                                          actions: [acceptAction, declineAction],
                                          intentIdentifiers: [],
                                          options: [])
    let center = UNUserNotificationCenter.current()
    center.setNotificationCategories([category])
    center.delegate = self
    center.requestAuthorization(options:[.alert, .sound, .badge]) { (granted: Bool, error: Error?) in
      if (error != nil) {
        print("Failed to request authorization.")
        return
      }
      if granted {
        application.registerForRemoteNotifications()
      } else {
        print("The user refused the push notification.")
      }
    }
  } else {
    // For iOS 8/iOS 9
    // Define notification actions for actionable notifications.
    let acceptAction = UIMutableUserNotificationAction()
    acceptAction.identifier = "ACCEPT_IDENTIFIER"
    acceptAction.title = "Accept"
    acceptAction.isDestructive = false

    let declineAction = UIMutableUserNotificationAction()
    declineAction.identifier = "DECLINE_IDENTIFIER"
    declineAction.title = "Decline"
    declineAction.isDestructive = true    // This action will appear in red.

    // Define a category for actionable notifications.
    let inviteCategory = UIMutableUserNotificationCategory()
    inviteCategory.identifier = "MESSAGE_CATEGORY"
    inviteCategory.setActions([acceptAction, declineAction], for: UIUserNotificationActionContext.default)
    inviteCategory.setActions([acceptAction, declineAction], for: UIUserNotificationActionContext.minimal)
    let categories : Set<UIUserNotificationCategory>= [inviteCategory]

    // Register the device to APNs.
    let notificationSettings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: categories)
    application.registerUserNotificationSettings(notificationSettings)
    application.registerForRemoteNotifications()
  }

  return true
}

Objective-C:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Initialize the Kii Cloud SDK.
  [Kii beginWithID:@"___APPID___"
            andKey:@"___APPKEY___"
           andSite:kiiSiteJP];

  // Register the device to APNs.
  if ([[UNUserNotificationCenter class] respondsToSelector:@selector(currentNotificationCenter)]) {
    // For iOS 10
    UNNotificationAction *acceptAction = [UNNotificationAction actionWithIdentifier: @"ACCEPT_IDENTIFIER"
                                                                              title: @"Accept"
                                                                            options: UNNotificationActionOptionNone];
    UNNotificationAction *declineAction = [UNNotificationAction actionWithIdentifier: @"DECLINE_IDENTIFIER"
                                                                               title: @"Decline"
                                                                             options: UNNotificationActionOptionDestructive];    // This action will appear in red.
    UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier: @"MESSAGE_CATEGORY"
                                                                              actions: @[acceptAction, declineAction]
                                                                    intentIdentifiers: @[]
                                                                              options: UNNotificationCategoryOptionNone];
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    NSSet *categories = [NSSet setWithObject:category];
    [center setNotificationCategories:categories];
    center.delegate = self;
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge)
                          completionHandler:^(BOOL granted, NSError * _Nullable error) {
      if (error != nil) {
        NSLog(@"Failed to request authorization.");
        return;
      }
      if (granted) {
        [application registerForRemoteNotifications];
      } else {
        NSLog(@"The user refused the push notification.");
      }
    }];
  } else {
    // For iOS 8/iOS 9
    // Define notification actions for actionable notifications.
    UIMutableUserNotificationAction *acceptAction = [[UIMutableUserNotificationAction alloc] init];
    acceptAction.identifier = @"ACCEPT_IDENTIFIER";
    acceptAction.title = @"Accept";
    acceptAction.destructive = NO;

    UIMutableUserNotificationAction *declineAction = [[UIMutableUserNotificationAction alloc] init];
    declineAction.identifier = @"DECLINE_IDENTIFIER";
    declineAction.title = @"Decline";
    declineAction.destructive = YES;    // This action will appear in red.

    // Define a category for actionable notifications.
    UIMutableUserNotificationCategory *inviteCategory =
    [[UIMutableUserNotificationCategory alloc] init];
    inviteCategory.identifier = @"MESSAGE_CATEGORY";

    [inviteCategory setActions:@[acceptAction, declineAction]
                    forContext:UIUserNotificationActionContextDefault];
    [inviteCategory setActions:@[acceptAction, declineAction]
                    forContext:UIUserNotificationActionContextMinimal];
    NSSet *categories= [NSSet setWithObject:inviteCategory];

    // Register the device to APNs.
    UIUserNotificationSettings* notificationSettings =
    [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert |
                                                 UIUserNotificationTypeSound |
                                                 UIUserNotificationTypeBadge
                                      categories:categories];
    [application registerUserNotificationSettings:notificationSettings];
    [application registerForRemoteNotifications];
  }

  return YES;
}

As with the initialization for push notifications without actions, the initialization API is different between iOS 9 or earlier and iOS 10 or later.

With iOS 10 or later, pass the information about the defined categories as the categories argument of the setNotificationCategories(_:) method to the UNUserNotificationCenter class. With iOS 8 and iOS 9, pass the information about the categories as the categories argument to the UIUserNotificationSettings class.

In this sample code, the delegate property of the UNUserNotificationCenter class holds self. Therefore, the UNUserNotificationCenterDelegate protocol must be added to the AppDelegate class.

Swift:

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

}

Objective-C:

// AppDelegate.h
@interface AppDelegate : UIResponder <UIApplicationDelegate, UNUserNotificationCenterDelegate>