APNs の初期化処理

ここでは、プッシュ通知設定チュートリアルの プログラムの実装 で実装した初期化処理の詳細と、機能の追加方法について、以下の内容を説明します。

プッシュ通知設定チュートリアルでは、プログラムの実装のステップで「シンプルなプッシュ通知の初期化」相当の初期化処理を実装しています。チュートリアルの処理をモバイルアプリでそのまま利用する場合、このページで説明している処理は別途実装する必要はありません。アクション付きプッシュ通知などの初期化処理を実装する際の参考にしてください。

シンプルなプッシュ通知の初期化

チュートリアル内では、AppDelegate クラスの application(_:didFinishLaunchingWithOptions:) メソッドで、以下のようにプッシュ通知の初期化を行っていました。

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.
}

チュートリアルの説明にあるように、この処理では、ユーザーにプッシュ通知を利用する許可を得た後、APNs への登録処理を行っています。結果として、デバイスのインストール に示す application(_:didRegisterForRemoteNotificationsWithDeviceToken:) メソッドで、APNs のデバイストークンを受け取ることができます。

また、プッシュ通知の初期化に失敗したときは、application(_:didFailToRegisterForRemoteNotificationsWithError:) メソッドでエラーを通知します。

アクション付きプッシュ通知の初期化

プッシュ通知の初期化では、基本的な API に加えて iOS のプッシュ通知に関連するさまざまな API を自由に実行できます。ここでは、アクション付きプッシュ通知を利用するための初期化について説明します。

アクション付きプッシュ通知とは、プッシュ通知を受信した際に下記のようなボタンでアクションを選択できる機能です。エンドユーザーは、通知アクションを選択することで、通知センターやロック画面から、プッシュ通知のメッセージに対して、直接モバイルアプリの操作を行うことができます。

通知アクションの表示形式は、エンドユーザーが iOS の設定画面を操作することで、バナー形式、ダイアログ形式、表示なしのいずれかを選択できます。通知アクションは通知センターやロック画面でも表示されます。バナー形式(上の画面)や通知センターでは 2 つまで、ダイアログ形式の場合のみ 4 つまでの通知アクションを表示できます。

ロック画面での表示は通知センターと同様ですが、実行にパスコードの入力が必要な通知アクションとするかどうかをプログラムから指定できます。

下記のように、1 つのモバイルアプリで通知アクションのセットを複数定義することができます。プッシュ通知を受け取ったとき、どの通知アクションのセットを使用するかは、プッシュ通知の送信元がプッシュメッセージで指定したカテゴリーによって決まります。

カテゴリーとそれに含まれる各通知アクションは、モバイルアプリからそれぞれ識別子を付けて初期化しておきます。ユーザーが画面操作によって通知アクションを選択すると、アプリに対してカテゴリーの識別子と、ユーザーが選択した通知アクションの識別子が渡されます。モバイルアプリでは、渡された識別子によって処理を振り分けることができます。

カテゴリーを指定するシナリオを下記の図の例を使って示します。

  1. 使用するカテゴリーと通知アクションを、モバイルアプリの初期化処理で登録しておきます。カテゴリーはそれぞれ CONTACT_CATEGORYMESSAGE_CATEGORY とし、通知アクションを図のように初期化します。

  2. プッシュメッセージの送信元が、メッセージ「連絡先の追加リクエストを受け取りました。」と、カテゴリー CONTACT_CATEGORY を付加して送信したとします。

  3. プッシュメッセージを受信すると、メッセージとともに、CONTACT_CATEGORY に対応する「許可」「無視」「ブロック」の選択肢が表示されます(ダイアログ形式以外では 2 つまでの選択肢が表示されます)。

  4. ユーザーが「許可」を選択したとすると、アプリの通知メソッドには、カテゴリー CONTACT_CATEGORY、通知アクション ACCEPT_IDENTIFIER がプッシュメッセージとともに渡されます。

サンプルコード

下記のサンプルコードでは、2 種類のカスタム通知アクション(AcceptDecline)を定義し、それを MESSAGE_CATEGORY というカテゴリーに割り当てています。

このサンプルコードでは、Kii Cloud SDK の初期化処理以外、すべて iOS の API によって構成されています。iOS の仕様に従って、任意のカスタマイズを行うことができます。これらの機能は Kii Cloud の機能範囲外であるため、詳細な情報が必要な場合は iOS のドキュメントや Web 上の一般的な技術情報をご覧ください。

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;
}

アクションを伴わないプッシュ通知の初期化と同様、iOS 10 以降とそれ以前で使用する API が異なります。

iOS 10 以降では、定義したカテゴリーの情報を UNUserNotificationCenter クラスの setNotificationCategories(_:) メソッドの categories 引数として渡します。iOS 8/iOS 9 では、カテゴリーの情報を UIUserNotificationSettings クラスの categories 引数として渡します。

なお、この実装では、UNUserNotificationCenter クラスの delegate プロパティに self を指定しているため、AppDelegate クラスに UNUserNotificationCenterDelegate プロトコルを追加する必要があります。

Swift:

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

}

Objective-C:

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