Implement Your Application

Now we will start implementing the initialization code and the reception handler.

Registering the device to APNs

Let us add initialization code for push notification to the application:didFinishLaunchingWithOptions: method in the AppDelegate class. You need to import the UserNotifications framework to execute the APIs that you add.

See the final source code below. This sample also includes the code that we had implemented to initialize Kii Cloud.

  • import UserNotifications
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
      Kii.begin(withID: "___APPID___", andKey: "___APPKEY___", andSite: KiiSite.US)
    
      // 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, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(notificationSettings)
        application.registerForRemoteNotifications()
      }
    
      return true
    }
  • import UserNotifications
    
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
      Kii.beginWithID("___APPID___", andKey: "___APPKEY___", andSite: KiiSite.US)
    
      // Register the device to APNs.
      if #available(iOS 10, *) {
        // For iOS 10
        UNUserNotificationCenter.currentNotificationCenter().requestAuthorizationWithOptions([.Alert, .Sound, .Badge], completionHandler: { (granted: Bool, error: NSError?) 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(forTypes: [.Alert, .Sound, .Badge], categories: nil)
        application.registerUserNotificationSettings(notificationSettings)
        application.registerForRemoteNotifications()
      }
    
      return true
    }
  • @import UserNotifications;
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      [Kii beginWithID:@"___APPID___"
                andKey:@"___APPKEY___"
               andSite:kiiSiteUS];
    
      // 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;
    }

This code asks the user for permission to enable the push notification feature and registers the device to APNs. This code declares to use the three notification styles: alerts (.alert), sounds (.sound), and icon badges (.badge). The prompt message includes these styles accordingly.

The APIs used in the initialization code are different between iOS 10 or later and iOS 9 or earlier.

  • iOS 10 or later

    The requestAuthorization method of the UNUserNotificationCenter class is called to ask the user for permission.

    The completionHandler is called after the user responds. The granted argument indicates if the user enabled the push notification feature. If the user did, the registerForRemoteNotifications method is called to register the device to APNs.

  • iOS 8/iOS 9

    For the OSes earlier than iOS 10, execute the registerUserNotificationSettings method that displays the prompt for permission to the user and the registerForRemoteNotifications method that registers the device to APNs.

Installing the device token to Kii Cloud

Next, associate the user with the device token obtained from APNs and register the token to Kii Cloud.

After the device is successfully registered to APNs, we call the application:didRegisterForRemoteNotificationsWithDeviceToken: method with the device token from APNs as the argument. If the registration fails, we call the application:didFailToRegisterForRemoteNotificationsWithError: method.

The above process is implemented as below:

  • func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
      let username = "user1"
      let password = "123ABC"
      KiiUser.authenticate(username, withPassword: password) { (user: KiiUser?, error: Error?) -> Void in
        if (error != nil) {
          print("Failed to authenticate: \((error! as NSError).userInfo["description"])")
          return
        }
        KiiPushInstallation.install(withDeviceToken: deviceToken, andDevelopmentMode: true) { (installation: KiiPushInstallation?, error: Error?) -> Void in
          if (error != nil) {
            print("Failed to install the device token: \((error! as NSError).userInfo["description"])")
            return
          }
          print("Push installed!")
        }
      }
    }
    
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
      print("Failed to register to APNs: \(error)")
    }
  • func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
      let username = "user1"
      let password = "123ABC"
      KiiUser.authenticate(username, withPassword: password) { (user: KiiUser?, error: NSError?) -> Void in
        if (error != nil) {
          print("Failed to authenticate: \(error!.userInfo["description"])")
          return
        }
        KiiPushInstallation.installWithDeviceToken(deviceToken, andDevelopmentMode: true) { (installation: KiiPushInstallation?, error: NSError?) -> Void in
          if (error != nil) {
            print("Failed to install the device token: \(error!.userInfo["description"])")
            return
          }
          print("Push installed!")
        }
      }
    }
    
    func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
      print("Failed to register to APNs: \(error)")
    }
  • - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
      NSString *username = @"user1";
      NSString *password = @"123ABC";
      [KiiUser authenticate:username withPassword:password andBlock:^(KiiUser *user, NSError *error) {
        if (error != nil) {
          NSLog(@"Failed to authenticate: %@", error.userInfo[@"description"]);
          return;
        }
        [KiiPushInstallation installWithDeviceToken:deviceToken
                                 andDevelopmentMode:YES
                                      andCompletion:^(KiiPushInstallation *installation, NSError *error2) {
          if (error != nil) {
            NSLog(@"Failed to install the device token: %@", error2.userInfo[@"description"]);
            return;
          }
          NSLog(@"Push installed!");
        }];
      }];
    }
    
    - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error {
      NSLog(@"Failed to register to APNs: (%@)", error);
    }

After the device is successfully registered to APNs, call the application:didRegisterForRemoteNotificationsWithDeviceToken: method. Then log in the user and install the device.

Log in to Kii Cloud with the authenticate method of KiiUser. Here we use the user that you set up when creating the iOS app. Specify the username and password of the test user in username and password. The sample code simply logs in the user with the fixed username user1 and the password 123ABC.

After the user successfully logs in, install the device token from APNs to Kii Cloud with the install method of KiiPushInstallation. The logged-in user and the device token are associated on Kii Cloud because the method is executed with the logged-in user's privilege. From now on, this device receives push notifications addressed to this user.

Note that the sample code installs the device with APNs in development mode. When you want to receive push notifications in production mode, set andDevelopmentMode to false (NO).

Installing at each startup

The device token needs to be installed each time the device starts up. If you move the code for getting the device token and installing it to Kii Cloud to other class, make sure to execute the code each time the mobile app starts.

The Local and Remote Notification Programming Guide by Apple also mentions that your app must register with APNs each time it launches. Kii Cloud might delete device tokens if it detects that the tokens are invalid in APNs. If the mobile app does not install a new device token to Kii Cloud, the device will not receive push notifications any longer.

Adding the reception handler

Next, let us implement the reception handler that will be executed when the device receives a push message. When you develop a real mobile app, you would implement some app features that use data extracted from messages, though this sample code just prints log messages.

  • func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
      print("Received the push notification: \(userInfo)")
      completionHandler(.newData)
    }
  • func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
      print("Received the push notification: \(userInfo)")
      completionHandler(.NewData)
    }
  • - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result)) completionHandler {
      NSLog(@"Received the push notification: %@", userInfo);
      completionHandler(UIBackgroundFetchResultNewData);
    }

When you implement the push notification feature in your mobile app, see Implementing the Initialization and Reception Processes for considering implementation of other handlers. The method introduced in this topic is sufficient if you just want to test the push notification feature.

This is all for the implementation. Let us move to the next step: Send Test Messages to check if the push notification really works.


<< Configure the Project in Xcode Send Test Messages >>