ページの先頭行へ戻る
Interstage Mobile Application Server V1.3.0 アプリケーション開発ガイド
FUJITSU Software

6.5.13 既読通知機能の利用

クライアント側で既読通知APIを利用することにより、受信したメッセージが確認されたことをIMAPSサーバへ通知することができます。
既読通知機能を利用するには定義ファイル(impush.properties)のfj_push_read_modeの設定が必要です。詳細は"運用ガイド"を参照してください。
既読通知は、通知メッセージ情報に含まれるメッセージIDを取得し、既読通知APIを使用します。メッセージIDの取得タイミングは以下となります。

Androidで既読通知機能を利用する場合は、プッシュクライアント設定ファイルのpush.NotificationMainClassNameに通知バータップ後に起動するActivityを設定してください。プッシュクライアント設定ファイルについては、付録D プッシュクライアント設定ファイルを参照してください。

注意

push.NotificationMainClassNameが省略、または存在しないクラスを指定していた場合は、アプリが起動しないためインテントを取得できません。

以下、既読API実装例です。

IMAPSプッシュ通知
IMAPSプッシュ通知での既読通知APIの実装例としては以下の二つのパターンがあります。
  • アプリ未起動時/起動時にメッセージ受信し、通知バーをタップしてアプリを起動した場合
    //アプリのMainActivity.java内(push.propertiesのpush.NotificationMainClassNameに設定)
    //通知バーをタップし、アプリを起動した際の処理
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Intent intent = getIntent();
      //インテントにmsgIDが設定されている場合
      if(intent != null && intent.getExtras() != null) {
          //インテントからメッセージIDを取得
               String msgID = intent.getStringExtra(PushDefine.EXTRA_MESSAGE_ID);
          PushManager pm = new PushManager(getApplicationContext());
                try {
               ArrayList<String> f_msgID = pm.getFailedMsgIDList();
              //アプリ領域にメッセージIDが保存されている場合
              if(f_msgID != null){
                    //保存されているメッセージID分の既読通知を実行
                  for(int i = 0; i < f_msgID.size(); i++) {
                            String id = f_msgID.get(i);
                  pm.notifyMessageRead(id);
                }
              }
              //タップしたメッセージの既読通知を実行 
              pm.notifyMessageRead(msgID);
                } catch(PushException e) {
                   //例外時の処理
                }
         } else {
           //インテントが取得できなかった場合の処理
         }       
    }
    
    //通知バータップで起動するActivityのlaunchModeが
    //"singleTop"、"singleTask"、"singleInstance"の場合
    protected void onNewIntent(Intent intent) {
      super.onNewIntent(intent);
      //インテントにmsgIDが設定されている場合
      if(intent != null && intent.getExtras() != null) {
          //インテントからメッセージIDを取得
               String msgID = intent.getStringExtra(PushDefine.EXTRA_MESSAGE_ID);
          PushManager pm = new PushManager(getApplicationContext());
                try {
               ArrayList<String> f_msgID = pm.getFailedMsgIDList();
              //アプリ領域にメッセージIDが保存されている場合
              if(f_msgID != null) {
                    //保存されているメッセージID分の既読通知を実行
                  for(int i = 0; i < f_msgID.size(); i++) {
                            String id = f_msgID.get(i);
                  pm.notifyMessageRead(id);
                }
              }
              //タップしたメッセージの既読通知を実行
              pm.notifyMessageRead(msgID);
                } catch(PushException e) {
                   //例外時の処理
                }
         } else {
           //インテントが取得できなかった場合の処理
         }       
    }
  • アプリが起動中にメッセージを受信し、アプリ側でPushReceiverを実装していた場合

    private class MyReceiver extends PushReceiver{
            @Override
            public void callback(int arg0, Bundle arg1) {
          //IMAPSプッシュのメッセージを受信した場合
                if(arg0 == com.fujitsu.fjh.push.common.PushDefine.RESULT_RECEIVE_MESSAGE) {
                   byte[] payloadData = arg1.getByteArray(com.fujitsu.fjh.push.common.PushDefine.MESSEAGE_BUNDLE_PAYLOAD_KEY);
                   String payload = new String(payloadData);
            //ペイロード情報をJSONObjectへ変換
            JSONObject payloadObject = new JSONObject(payload);
                   //ペイロード情報からmsgIDを取得
                   String msgid = payloadObject.getString("mid")
            //受信時の処理を実装  
            //   ・・・
                   //メッセージを確認したタイミング(任意)で既読通知を実行
            PushManager pm = PushManager.getInstance();
                   try {
                       ArrayList<String> f_msgID = pm.getFailedMsgIDList();
                  //アプリ領域にメッセージIDが保存されている場合
                  if(f_msgID != null) {
                        //保存されているメッセージID分の既読通知を実行
                      for(int i = 0; i < f_msgID.size(); i++) {
                              String id = f_msgID.get(i);
                      pm.notifyMessageRead(id);
                    }
                  }
                //受信したメッセージの既読通知を実行
                pm.notifyMessageRead(msgid);
              } catch(PushException e) {
                       //例外時の処理
                   }
        }
    }
GCMプッシュ通知
GCMプッシュ通知での既読通知APIの実装例としては以下の二つのパターンがあります。
  • アプリ未起動時/起動時にメッセージ受信し、通知バーをタップしてアプリを起動した場合
    //アプリのMainActivity.java内(push.propertiesのpush.NotificationMainClassNameに設定)
    //通知バーをタップし、アプリを起動した際の処理
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      Intent intent = getIntent();
      //インテントにmsgIDが設定されている場合
      if(intent != null && intent.getExtras() != null) {
          //インテントからメッセージIDを取得
               String msgID = intent.getStringExtra(PushDefine.EXTRA_MESSAGE_ID);
          GcmRegister gr = GcmRegister.getInstance(getApplicationContext());
                try {
               ArrayList<String> f_msgID = gr.getFailedMsgIDList();
              //アプリ領域にメッセージIDが保存されている場合
              if(f_msgID != null) {
                    //保存されているメッセージID分の既読通知を実行
                  for(int i = 0; i < f_msgID.size(); i++) {
                           String id = f_msgID.get(i);
                  gr.notifyMessageRead(id);
                }
              }
              //タップしたメッセージの既読通知を実行 
              gr.notifyMessageRead(msgID);
                } catch(PushException e) {
                   //例外時の処理
                }
         } else {
           //インテントが取得できなかった場合の処理
         }       
    }
    
    //通知バータップで起動するActivityのlaunchModeが
    //"singleTop"、"singleTask"、"singleInstance"の場合
    protected void onNewIntent(Intent intent) {
      super.onNewIntent(intent);
      //インテントにmsgIDが設定されている場合
      if(intent != null && intent.getExtras() != null) {
          //インテントからメッセージIDを取得
               String msgID = intent.getStringExtra(PushDefine.EXTRA_MESSAGE_ID);
          GcmRegister gr = GcmRegister.getInstance(getApplicationContext());
               try {
               ArrayList<String> f_msgID = gr.getFailedMsgIDList();
              //アプリ領域にメッセージIDが保存されている場合
              if(f_msgID != null) {
                    //保存されているメッセージID分の既読通知を実行
                  for(int i = 0; i < f_msgID.size(); i++) {
                           String id = f_msgID.get(i);
                  gr.notifyMessageRead(id);
                }
              }
              //タップしたメッセージの既読通知を実行 
              gr.notifyMessageRead(msgID);
                } catch(PushException e) {
                   //例外時の処理
                }
         } else {
           //インテントが取得できなかった場合の処理
         }       
    }
  • アプリが起動中にメッセージを受信し、アプリ側でPushReceiverを実装していた場合
    private class MyReceiver extends PushReceiver {
            @Override
            public void callback(int arg0, Bundle arg1) {
          //GCMプッシュのメッセージを受信した場合
                if(arg0 == com.fujitsu.fjh.push.common.PushDefine.RESULT_RECEIVE_GCM_MESSAGE) {
                   Bundle payloadData = arg1.getBundle (com.fujitsu.fjh.push.common.PushDefine.MESSEAGE_BUNDLE_PAYLOAD_KEY);
                   String msgID = payloadData.getString("mid")
                   //受信時の処理を実装
            //   ・・・
            //メッセージを確認したタイミング(任意)で既読通知を実行
            GcmRegister gr = GcmRegister.getInstance(getApplicationContext());
            try {
                       ArrayList<String> f_msgID = gr.getFailedMsgIDList();
                  //アプリ領域にメッセージIDが保存されている場合
                  if(f_msgID != null) {
                        //保存されているメッセージID分の既読通知を実行
                      for(int i = 0; i < f_msgID.size(); i++) {
                               String id = f_msgID.get(i);
                      gr.notifyMessageRead(id);
                    }
                  }
                //受信したメッセージの既読通知を実行
                gr.notifyMessageRead(msgid);
              } catch(PushException e) {
                       //例外時の処理
                   }
        }
    }
APNsプッシュ通知
APNsプッシュ通知での既読通知APIの実装例としては以下の二つのパターンがあります。
  • アプリ未起動時にメッセージ受信し、通知センターをタップしてアプリを起動した場合
    AppDelegateクラス内
    //通知センターのメッセージをタップし、アプリを起動した際の処理
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
       NSDictionary *userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
         if(userInfo != nil)
         {
             FJPPayloadInfo* payInfo = [[FJPPayloadInfo alloc]initWithPayload:userInfo];
             //アクションを指定した通知の場合は、親クラスの関数を実行する前に既読通知を行う
             if(payInfo != nil && payInfo.msgID != nil)
             {
                //既読通知を実行
            NSArray* f_msgid = [FJPMessageReadManager getFailedMsgIDList];
            //アプリ領域にメッセージIDが保存されている場合
                if(f_msgid != nil)
             {
              //保存されているメッセージID分の既読通知を実行
              for(NSString* id in f_msgid)
              {
                  [FJPMessageReadManager notifyMessageRead:id delegate:self]; 
              }
            }
            //タップしたメッセージの既読通知を実行
               [FJPMessageReadManager notifyMessageRead:payInfo.msgID delegate:self]; 
             }
         }
         [super application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions];
         //アクション指定がない通知は親クラスの関数実行後でも既読通知を行える
         //既読通知を実行
         //・・・
         return YES;
    }
  • アプリ起動中にメッセージ受信した場合

    アプリ起動中にメッセージを受信した場合、FJPAppDelegateクラスを継承したサブクラスのdidReceiveRemoteNotification関数内でペイロード情報からメッセージIDを取得し、既読通知APIを実行します。 また、メッセージIDは、ペイロード情報をFJPPayloadInfoオブジェクトに変換して取得します。

    AppDelegateクラス内
    //アプリ起動中にプッシュ通知を受信した場合 
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
     {
        if (userInfo != nil) 
        {
            // ペイロード情報をFJPPayloadInfoオブジェクトに初期化
            FJPPayloadInfo* payInfo = [[FJPPayloadInfo alloc]initWithPayload:userInfo];
            //payload情報にmsgIDが格納されている場合
            if(payInfo != nil && payInfo.msgID != nil)
            {
          //受信時の処理を実装
               //    ・・・
           //メッセージを確認したタイミング(任意)で既読通知を実行
          NSArray* f_msgid = [FJPMessageReadManager getFailedMsgIDList];
          //アプリ領域にメッセージIDが保存されている場合
               if(f_msgid != nil)
          {
            //保存されているメッセージID分の既読通知を実行
            for(NSString* id in f_msgid)
            {
              [FJPMessageReadManager  notifyMessageRead:id delegate:self]; 
            }
          }
          //受信したメッセージの既読通知を実行
               [FJPMessageReadManager  notifyMessageRead:payInfo.msgID delegate:self]; 
            }
        }
    }
    また、既読通知APIの通知結果を受け取る場合は、FJPNotifyDelegateプロトコルのdidNotifyMessageRead関数をアプリ側で実装します。以下は実装例です。
    AppDelegateクラス内
    @interface AppDelegate : FJPAppDelegate <FJPNotifyDelegate>	
    -	(void)didNotifyMessageRead:(NSError*) error
    @end
    
    #pragma mark FJPNotifyDelegate implementation
    -	(void)didNotifyMessageRead:(NSError*) error
    {
        if(error == nil)
        {
            //通知成功の場合の処理
        }
        else
            {
            //通知失敗の場合の処理
            }
    }
WNSプッシュ通知
WNSプッシュ通知での既読通知APIの実装例としては以下のパターンがあります。
  • アプリ未起動時/起動時にメッセージ受信し、トースト通知をタップしてアプリを起動した場合
    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        Frame rootFrame = Window.Current.Content as Frame;
        ・・・
        Window.Current.Activate();
        //PushReceiverを継承したクラスのインスタンス生成
        MyReceiver myreceiver = new MyReceiver();
        WNSRegister wr = WNSRegister.getInstance(myreceiver);
        //既読通知に失敗したメッセージIDを取得し、再度既読通知を行う
        IList<string> list = wr.getFailedMsgIDList();
        try
        {
          if(list != null)
       {
          //既読通知に失敗したメッセージID分、既読通知を実行する
          foreach(string f_msgid in list)
             {
             wr.notifyMessageRead(f_msgid);
          });
       }
          //LaunchActivatedEventArgsのArgumentsプロパティからメッセージIDを取得する
          string msgid = wr.getMessageID(e.Arguments);
          //既読通知を実行する
          wr.notifyMessageRead(msgid);
        }
        catch(Exception e)
        {
       //例外時の処理
        }
        //アクションを実行する
        WNSToastAction.action(e.Arguments, e.Kind);
    }
・ハイブリッドアプリでの既読通知について
  • Android、iOSのハイブリッドアプリで既読通知を行う場合は、ネイティブ層で既読APIの実装が必要です。

    Android はインテントからメッセージIDを取得する方法のみ有効です。

    そのため、アプリ起動中においても通知バーをタップし、インテントからメッセージIDを取得する方法で既読通知を行うようにしてください。
  • Windowsのハイブリッドアプリで既読通知を行う場合は、WinJSを利用することにより、JavaScriptでネイティブ用の既読APIを使用することができます。以下、実装例です。
    //activatedイベントにハンドラ-を登録
    WinJS.Application.addEventListener("activated", onActivatedHandler, false);
    function onActivatedHandler(args) {
        if (args.detail.arguments !== "") {
            //既読通知処理
            try {
                //メッセージID取得
                var msgid = Com.Fujitsu.Imaps.Push.WNS.WNSRegister.getInstance().getMessageID(args.detail.arguments);
                //既読通知の実行
                Com.Fujitsu.Imaps.Push.WNS.WNSRegister.getInstance().notifyMessageRead(msgid);
            }
            //WinJSの制限により、nullが返る場合はArgumentNullExceptionが発生する(getMessageID返却値がnull)
            catch (e) {
                //例外時の処理
            }
            //アクションの実行
            Com.Fujitsu.Imaps.Push.WNS.WNSToastAction.action(args.detail.arguments, args.detail.kind);
        }
    }
・制限事項
・プッシュ受信アプリ以外のアクションを指定したプッシュ通知にて、既読通知を行う場合について
メッセージタップ後のアクションに、プッシュ受信アプリ以外のアプリのアクション(メール送信画面起動、ブラウザ起動など)を指定し、そのプッシュ通知にて既読通知を行う場合は、Android、iOSにおいて以下の制限があります。

※Windowsの場合は、プッシュ受信アプリ以外のアプリのアクションを指定したプッシュ通知に対しても、既読通知を行うことができます。

[Android]
ネイティブアプリ

アクション指定した通知をタップし起動するのは、アクションに指定されたアプリです。

そのため、アクションにプッシュ受信アプリ以外のアクションを指定していた場合は、それらのアプリ(ブラウザ、メールなど)が起動します。 つまり、プッシュ受信アプリが未起動時の場合は、通知をタップしてもプッシュ受信アプリは起動しません。 プッシュ受信アプリが起動しないため、既読通知APIを実行することができません。

プッシュ受信アプリが起動中の場合は、PushReceiverを利用してメッセージIDを取得することで、 アプリがフォアグラウンド(アクション実行前)の場合のみ既読通知を実行することができます。

ハイブリッドアプリ

Androidのハイブリッドアプリの場合、プッシュ受信アプリが未起動時・起動中共に既読通知APIを実行することができません。

これは、Androidのハイブリッドアプリでは、通知バーをタップしインテントからメッセージIDを取得する方法でのみ既読通知することが可能なのですが、 通知バーのタップによりプッシュ受信アプリ以外のアプリ(ブラウザ、メールなど)が起動し、 プッシュ受信アプリが起動しないため、既読通知APIを実行することができないからです。

[iOS]
ネイティブアプリ

プッシュ受信アプリ未起動時は、FJPAppDelegateの派生クラスのdidFinishLaunchingWithOptions関数内で渡されたパラメータからメッセージIDを取得し、既読通知APIを実行することができます。 ただし、親クラスの同関数を実行する前(アプリ起動後のアクション実行前)でのみ有効です。

プッシュ受信アプリ起動中においても、FJPAppDelegateの派生クラスのdidReceiveRemoteNotification関数内で渡されたパラメータからメッセージIDを取得し、既読通知APIを実行することができます。 ただし、プッシュ受信アプリ未起動時と同様に、親クラスの同関数を実行する前でのみ有効です。

・WNSのタイル通知とバッジ通知について
WNSのタイル通知とバッジ通知での既読通知機能は未サポートです。
・登録IDの更新について
既読通知の前後で登録IDが更新された場合、そのメッセージに対しての既読通知は成功せずに、登録IDの不一致としてパラメータエラーになります。 そのため、未読状態が続いているようなメッセージは上記エラーとなることがあります。
・利用不可のファイル名(キー名)
[Android]
SharedPreferencesの下記ファイル名はメッセージIDの保存に使用するため、使用しないでください。

・com_fujitsu_push_msg_id_data

[iOS]
NSUserDefaultsの下記キー名はメッセージIDの保存に使用するため、使用しないでください。

・com_fujitsu_push_msg_id_data

[Windows]
ApplicationData.Current.LocalSettingsの下記キー名はメッセージIDの保存に使用するため、使用しないでください。

・com_fujitsu_push_msg_id_data

・Androidでのメッセージタップ後に起動するActivityについて

メッセージをタップ後に起動するActivityのlaunchModeが省略もしくは、"standard" が設定されていた場合は、メッセージタップにてActivityを初回起動後、メッセージを受信し、 その後メッセージをタップしても新規Activityが起動せず、前回のActivityが表示され、 onCreate()やonNewIntent()などのライフサイクルイベントにてメッセージIDが取得できず、既読通知を行うことができません。

そのため、メッセージタップ後に起動するActivityのlaunchModeは、"singleTop"、"singleTask"、"singleInstance" のいずれかを指定してください。