Android * Firebase(GCM)でバックグラウンドから受け取った通知を処理する


フォアグラウンドで通知を受け取った時とバックグラウンドで受け取った時の挙動と取得可能なデータが違う。
具体的言うとtitleやbodyなどが取得できない。

その他参考
Firebase を使用してAndroidのプッシュ通知を実装する
mBaasのFirebaseの機能と料金体系についてざっくり調べてみた








面倒ですがデータの形式を考える必要があります。
http://stackoverflow.com/questions/39046270/google-fcm-getintent-dont-returning-expected-data-when-app-is-in-background-stat


以下のようなデータをプッシュ通知する場合について考えます。
{ "to":"deviceid","priority":"high", "notification":{ "title": "title", "body": "新しい更新があります" }, "data":{ "url":"market://details?id=com.android.chrome" }, "icon":"myicon" }
更新を通知してplayストアへのurlを受け渡すといったイメージ(実際は自動更新されるからいらないけどね)



curlコマンドだと以下のようになります。

curl --header "Authorization: key=key" --header "Content-Type:application/json" https://fcm.googleapis.com/fcm/send -d "{\"to\":\"deviceid\",\"priority\":\"high\",\"notification\": {\"title\": \"title\", \"body\": \"新しい更新があります\"},\"data\":{\"url\":\"market://details?id=com.android.chrome\"}, \"icon\":\"myicon\" }"
keyとデバイスID(to)は各自で置き換えること



ただしこれだとバックグラウンドから通知をタップして起動したときに想定した値を取得できません。
通知にtitleとbodyが表示されますがソースコードから取得する手段がなくなってしまいます。

よって以下のように通知内容を変更します。
{ "to":"deviceid","priority":"high", "notification":{ "title": "title", "body": "新しい更新があります" }, "data":{ "url":"market://details?id=com.android.chrome" "title": "title", "body": "新しい更新があります" }, "icon":"myicon" }
dataペイロードへ追加することによってバックグラウンドから通知をタップした場合もtitle,bodyが取得できるようになります。



サンプル


kotlinで書いてるけどjavaと似たようなものなので各自置き換えてください。


アクティビティのonCreateから通知内容を取得する

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  // 通知情報の取得
  if (intent.extras != null) {
    for (key in intent.extras.keySet()) {
        val value = intent.extras.get(key)
      Log.d("notification", "Key: $key Value: $value")
      if( key == "url" ) {
        // Preferencesなどに保存する
      }
      if( key == "body" ) {
        // Preferencesなどに保存する
      }
    }
  }


通知からアプリを起動したときにif(intent.extras... の中が実行されます。



通知サービスFirebaseMessagingServiceを継承したクラスで通知データを処理する

class MyFirebaseMessagingService : FirebaseMessagingService() {
  override fun onMessageReceived(remoteMessage: RemoteMessage?) {
  Log.d(TAG, "From: " + remoteMessage!!.from)

  // Check if message contains a data payload.
  if (remoteMessage.data.size > 0) {
    Log.d(TAG, "Message data payload: " + remoteMessage.data)

    for( key in remoteMessage.data.keys ) {
      if( key == "url" ) {
        // remoteMessage.data[key] as String をPreferencesなどに保存する
      }
      if( key == "body" ) {
        // remoteMessage.data[key] as String をPreferencesなどに保存する
      }
    }

  }

ちなみにこっちはフォアグラウンドにあるときに通る処理なのでremoteMessage.data.body あたりで取得することができます。
今回は処理を共通化する事も考えてdataから取得しています。

Preferencesなどに保存して処理をすれば共通化できると思います。



2017年1月7日土曜日