メッセージの受信

ユーザープッシュ通知は、受信ハンドラー および ユーザーアクションのハンドラー で受け取ります。

以下のサンプルコードでは、AppDelegate クラスの application(_:didReceiveRemoteNotification:fetchCompletionHandler:) メソッドで、プッシュ通知の詳細を取得する例を示します。

Swift:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
  print("Received notification : \(userInfo)")

  // Create a KiiReceivedMessage instance from userInfo.
  let message = KiiReceivedMessage(fromAPNS: userInfo)

  // Get the sender of the push message.
  if (message.senderUser() != nil) {
    // If the sender is a user, get the user.
    let aUser = message.senderUser()
    // Refresh the user and then access it.
  } else if (message.senderThing() != nil) {
    // If the sender is a thing, get the thing.
    let aThing = message.senderThing()
    // Refresh the thing and then access it.
  } else {
    // The message has no sender information.
  }

  // Extract the target scope.
  let scopeType = message.getValueOf(.SCOPE_TYPE)!
  switch(scopeType){
  case "APP_AND_GROUP" :
    // If the subscribed topic is in a group scope, get the group.
    let aGroup = message.eventSourceGroup()
    // Refresh the group and then access it.
    break
  case "APP_AND_USER" :
    // If the subscribed topic is in a user scope, get the user.
    let aUser = message.eventSourceUser()
    // Refresh the user and then access it.
    break
  case "APP_AND_THING" :
    // If the subscribed topic is in a thing scope, get the thing.
    let aThing = message.eventSourceThing()
    // Refresh the thing and then access it.
    break
  default:
    // The subscribed topic is in the application scope.
    break;
  }

  // Get the topic name.
  let topicName = message.getValueOf(.TOPIC)

  // Get the topic.
  let aTopic = message.eventSourceTopic;

  completionHandler(.newData)
}

Objective-C:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result)) completionHandler {
  NSLog(@"Received notification: %@", userInfo);

  // Create a KiiReceivedMessage instance from userInfo.
  KiiReceivedMessage *message = [KiiReceivedMessage messageFromAPNS:userInfo];

  // Get the sender of the push message.
  if (message.senderUser != nil) {
    // If the sender is a user, get the user.
    KiiUser *aUser = message.senderUser;
    // Refresh the user and then access it.
  } else if (message.senderThing != nil) {
    // If the sender is a thing, get the thing.
    KiiThing *aThing = message.senderThing;
    // Refresh the thing and then access it.
  } else {
    // The message has no sender information.
  }

  // Extract the target scope.
  NSString *scopeType = [message getValueOfKiiMessageField:KiiMessage_SCOPE_TYPE];
  if ([@"APP_AND_GROUP" isEqualToString: scopeType]) {
    // If the subscribed topic is in a group scope, get the group.
    KiiGroup *aGroup = message.eventSourceGroup;
    // Refresh the group and then access it.
  } else if ([@"APP_AND_USER" isEqualToString: scopeType]) {
    // If the subscribed topic is in a user scope, get the user.
    KiiUser *aUser = message.eventSourceUser;
    // Refresh the user and then access it.
  } else if ([@"APP_AND_THING" isEqualToString: scopeType]) {
    // If the subscribed topic is in a thing scope, get the thing.
    KiiThing *aThing = message.eventSourceThing;
    // Refresh the thing and then access it.
  } else {
    // The subscribed topic is in the application scope.
  }

  // Get the topic name.
  NSString *topicName = [message getValueOfKiiMessageField:KiiMessage_TOPIC];

  // Get the topic.
  KiiTopic *aTopic = message.eventSourceTopic;

  completionHandler(UIBackgroundFetchResultNewData);
}

このサンプルコードでは、KiiReceivedMessage インスタンスから以下の情報を取得しています。

  1. トピックに対してプッシュメッセージを送信したユーザーまたは Thing を、senderUser() メソッドまたは senderThing() メソッドで取得します。

  2. getValueOf(_:) メソッドを実行し、プッシュメッセージより以下のフィールドを抽出します。

    • .SCOPE_TYPE:トピックのスコープ
    • .TOPIC:監視対象のトピック名
  3. eventSourceTopic プロパティから KiiTopic インスタンスを取得します。

プッシュメッセージの解釈の方法や、フィールド値の抽出方法の詳細については appledoc を参照してください。

通知センターからのプッシュメッセージを扱う場合は、ユーザーアクションのハンドラー も同様に実装します。リンク先のサンプルコードでは、ペイロードから KiiReceivedMessage を生成する方法が記述されています。このページのサンプルコードと同様、KiiReceivedMessage インスタンスから、プッシュ通知の詳細を取得できます。

なお、受信ハンドラーとユーザーアクションのハンドラーが連続して呼び出されたり、1 回のプッシュ通知で複数回の呼び出しが発生する場合があります。受信メソッドの組み合わせ に示すメソッドの呼び出しタイミングに従って、重複する処理の削除などの機能を作り込んでください。

プッシュ通知を期待どおりに受け取れない場合、トラブルシューティング を参考に問題を解決してください。また、プッシュ通知設定チュートリアル にあるシンプルな実装によって、プッシュ通知の動作だけを検証することもできます。

プッシュ通知の種類の判定

プッシュ通知の受信ハンドラーと、ユーザーアクションのハンドラーでは、このモバイルアプリに対するすべてのプッシュ通知を受け取ります。

モバイルアプリに対して通知されたメッセージが、サーバー上変更のプッシュ通知、ユーザープッシュ通知、管理者メッセージのプッシュ通知のうちどの機能で生成されたかは、ペイロード内のキーを確認することで識別できます。appledoc の KiiReceivedMessage の説明には、機能ごとに参照可能なフィールドが記載されています。これを元に、プッシュ通知の機能の種類を判断してください。

プッシュメッセージの例

以下は、プッシュメッセージを受け取ったとき、userInfo によって取得できるデータのイメージです。ユーザープッシュ通知では、通知されたトピック名や、アプリケーションから指定した追加データ(ここでは Key1 = Value1)を上記のメソッドによって取得できます。これらのデータの詳細は appledoc を参照してください。

{
    aps =     {
        alert =         {
            body = Alert;
        };
        badge = "-1";
    };
    Key1 = Value1
    s = "01234567-89ab-cdef-0123-456789abcdef";
    sa = 0123abcd;
    st = "APP_AND_USER";
    su = "01234567-89ab-cdef-0123-456789abcdef";
    to = myTopic;
    w = 1403844623139;
}

プッシュ通知のループに対する注意

プッシュ通知の設計や実装を行うときには、プッシュ通知のループが発生しないように十分に注意してください。プッシュ通知の受信処理で再びプッシュが発生する処理を行うと、永久ループから抜け出せなくなります。

ユーザープッシュ通知(Push to User)では、プッシュメッセージの受信処理を契機に、再びトピックへのメッセージ送信を行うと、プッシュ通知のループが発生する可能性があります。

万一、永久ループがリリースモジュールで発生してしまった場合、対処が非常に困難です。本質的には、すべてのエンドユーザーのモバイルアプリを対処済みバージョンに更新する必要があります。更新完了までは、開発者ポータルのプッシュ通知のキーや証明書を削除したり、ユーザーごとに REST API で購読を解除したりするなどの対処が必要になります。