メッセージの受信

プッシュ通知を受け取るには、AndroidManifest.xml でメッセージ受け取り用に指定した FirebaseMessagingService または BroadcastReceiver を実装します。この際、ヘルパー API を利用できます。

プッシュメッセージを受け取り、内容をパースする例を以下に挙げます。実装方法は FCM と JPush で異なります。

  • public class MyFirebaseMessagingService extends FirebaseMessagingService {
      @Override
      public void onMessageReceived(RemoteMessage remoteMessage) {
        // Get the push message.
        Map<String, String> payload = remoteMessage.getData();
        ReceivedMessage message = PushMessageBundleHelper.parse(payload);
    
        // Get the sender of the push message.
        KiiUser sender = message.getSender();
        // Refresh the sender and then access it.
    
        // Determine the push notification type and start parsing.
        PushMessageBundleHelper.MessageType type = message.pushMessageType();
        switch (type) {
          case PUSH_TO_APP:
            PushToAppMessage pam = (PushToAppMessage) message;
            // Extract the target scope.
            switch(pam.getScope()) {
              case APP_AND_GROUP:
                KiiGroup group = pam.getEventSourceGroup();
                // Refresh the group and then access it.
                break;
              case APP_AND_USER:
                KiiUser user = pam.getEventSourceUser();
                // Refresh the user and then access it.
                break;
              case APP_AND_THING:
                KiiThing thing = pam.getEventSourceThing();
                // Refresh the thing and then access it.
                break;
            }
    
            // Extract the subscribed bucket and the changed KiiObject.
            if (pam.containsKiiBucket()) {
              KiiBucket bucket = pam.getKiiBucket();
              if (pam.containsKiiObject()) {
                KiiObject obj = pam.getKiiObject();
              }
    
              // Extract field values.
              long when = pam.getMessage().getLong("when");
              String event_type = pam.getMessage().getString("type");
            }
            break;
          case PUSH_TO_USER:
            // Handle the "Push to User" message.
            break;
          case DIRECT_PUSH:
            // Handle the "Direct Push" message.
            break;
        }
      }
    }
  • public class KiiPushBroadcastReceiver extends BroadcastReceiver {
      @Override
      public void onReceive(Context context, Intent intent) {
        // Get the message type of JPush.
        String jpushMessageType = intent.getAction();
    
        if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(jpushMessageType)) {
          // Get the message as a Bundle instance.
          Bundle extras = intent.getExtras();
    
          // Get the message as a ReceivedMessage instance by parsing the bundle.
          ReceivedMessage message = PushMessageBundleHelper.parse(extras);
    
          // Get the sender of the push message.
          KiiUser sender = message.getSender();
          // Refresh the sender and then access it.
    
          // Determine the push notification type and start parsing.
          PushMessageBundleHelper.MessageType type = message.pushMessageType();
          switch (type) {
            case PUSH_TO_APP:
              PushToAppMessage pam = (PushToAppMessage) message;
              // Extract the target scope.
              switch(pam.getScope()) {
                case APP_AND_GROUP:
                  KiiGroup group = pam.getEventSourceGroup();
                  // Refresh the group before accessing it.
                  break;
                case APP_AND_USER:
                  KiiUser user = pam.getEventSourceUser();
                  // Refresh the user before accessing it.
                  break;
                case APP_AND_THING:
                  KiiThing thing = pam.getEventSourceThing();
                  // Refresh the thing before accessing it.
                  break;
              }
    
              // Extract the subscribed bucket and the changed KiiObject.
              if (pam.containsKiiBucket()) {
                KiiBucket bucket = pam.getKiiBucket();
                if (pam.containsKiiObject()) {
                  KiiObject obj = pam.getKiiObject();
                }
    
                // Extract field values.
                long when = pam.getMessage().getLong("when");
                String event_type = pam.getMessage().getString("type");
              }
              break;
            case PUSH_TO_USER:
              // Handle the "Push to User" message.
              break;
            case DIRECT_PUSH:
              // Handle the "Direct Push" message.
              break;
          }
        }
      }
    }

FCM では FirebaseMessagingService のサブクラスとして実装します。onMessageReceived メソッドの引数で得られたペイロードを PushMessageBundleHelper.parse メソッドに渡して、ReceivedMessage を作成します。

JPush では BroadcastReceiver のサブクラスとして実装します。onReceive メソッドで、通知がプッシュメッセージの受信であることを確認した後、第 2 引数の Intent から intent.getExtras() を利用し、プッシュメッセージのペイロードを Bundle で受信できます。Bundle を PushMessageBundleHelper.parse メソッドに渡して ReceivedMessage を作成します。

ReceivedMessage を作成後、以下の方法でプッシュメッセージの詳細を取得できます。

  1. getSender メソッドを実行して、プッシュメッセージの送信者を取得。
  2. pushMessageType メソッドを実行して、プッシュメッセージの種別を判別。
    (サーバー上の変更のプッシュ通知の場合、種別は "PUSH_TO_APP")
  3. getScope メソッドで対象のスコープを特定し、スコープに応じた getEventSourceGroupgetEventSourceUsergetEventSourceThing を実行してスコープオブジェクトを取得。
  4. getKiiBucket メソッドと getKiiObject メソッドを実行し、対象 Bucket と Object をそれぞれ取得。
  5. getMessage メソッドを実行してメッセージの Bundle を取得し、その他の既定フィールドやアプリ定義フィールドの値を取得。

この方法で KiiObject を作成したとき、インスタンス内のキーと値のペアは空のままです。このままでも Kii Cloud へのリクエストはできますが、キーと値のペアの内容を参照したい場合は refresh メソッドを実行してください。

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

ステータスバーへの表示

Android では、プッシュ通知を受信しても onMessageReceived メソッド、または、onReceive メソッドが呼ばれるだけです。特に、ステータスバーにメッセージを表示したいような場合は、自分で作り込む必要があります。実装のヒントは、プッシュ通知の実装ヒント をご覧ください。

プッシュメッセージの送信者

プッシュメッセージの送信者を取得する方法を以下に示します。Push to App での送信者は、講読中の Bucket に変更を行ったユーザーまたは Thing を表します。

PushToAppMessage pam = (PushToAppMessage) message;

// Get the sender of the push message.
KiiUser user = message.getSender();
// Refresh the user and then access it.

// Get the sender of the push message.
KiiPushMessageSender sender = message.getPushMessageSender();
if (sender instanceof KiiUser) {
  KiiUser senderUser = (KiiUser)sender;
  // Refresh the user and then access it.
} else if (sender instanceof KiiThing) {
  KiiThing senderThing = (KiiThing)sender;
  // Refresh the thing and then access it.
}

送信者を取得するには、以下のいずれかのメソッドを使用します。

  • getSender()

    Bucket に変更を行ったのがユーザーであった場合、そのユーザーを返します。Thing や、開発者ポータルのデータブラウザーからの変更の場合は null を返します。

  • getPushMessageSender()

    Bucket に変更を行ったのがユーザーまたは Thing であった場合、そのユーザーまたは Thing を返します。目的の型にキャストして参照します。開発者ポータルのデータブラウザーからの変更の場合は null を返します。

プッシュメッセージの例

以下は、FCM からのプッシュメッセージを受け取ったとき、remoteMessage.getData() によって取得できるデータのイメージです。Push to App では、更新があった Bucket や Object、その更新の種類(追加された、削除されたなど)のような情報を上記のメソッドによって取得できます。

これらのデータの詳細は Javadoc を参照してください。なお、Javadoc にないフィールドは FCM によって追加されたフィールドです。詳細は Google のドキュメントを参照してください。

{
    bucketType = rw,
    modifiedAt = 1403845696260,
    bucketID = bucketName,
    origin = EVENT,
    from = 123456789012,
    type = DATA_OBJECT_CREATED,
    objectScopeUserID = 01234567-89ab-cdef-0123-456789abcdef,
    objectScopeAppID = 0123abcd,
    sender = 01234567-89ab-cdef-0123-456789abcdef,
    collapse_key = bucketName,
    objectID = fedcba09-8765-4321-fedc-ba0987654321,
    when = 1403845696274,
    objectScopeType = APP_AND_USER,
    appID = 0123abcd
}

Push to App では、プッシュメッセージの内容をカスタマイズできません。回避方法は こちら をご覧ください。

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

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

サーバー上変更のプッシュ通知(Push to App)では、プッシュメッセージの受信処理を契機に、再び Bucket の更新を行うと、プッシュ通知のループが発生する可能性があります。

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