FCMを使ってバックグラウンド時にも指定したアイコンを表示させる

こんにちは[@u_nation](https://twitter.com/u_nation) です。

いきなり結論から言うと[**Firebase Cloud Messaging HTTP Protocol**](https://firebase.google.com/docs/cloud-messaging/http-server-ref)を使って解決できました。curlやREST Client( [DHC](https://chrome.google.com/webstore/detail/dhc-rest-client/aejoelaoggembcahagimdiliamlcdmfm)、[Advanced-Rest-Client](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo?gl=JP&hl=ja)など )を使って必要なデータをJson形式で送信します。

##ハマった点
Firebase Notificationsが発表されて、Webのコンソールからプッシュ通知ができると期待に胸躍らせた方も多いと思います。

しかし、アプリのバックグラウンド/フォアグラウンドで挙動が違うため、バックグラウンド時には[*FirebaseMessagingService*](https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService#public-constructors)でプッシュ通知をキャッチしてくれず、グレーの背景にアイコンを白塗りした残念なものが表示されます。。
<img width="819" alt="スクリーンショット 2016-07-02 21.39.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/7fe5c704-7f5a-5836-b179-d58f2c62925a.png">

Firebaseハンズオンで直接Googleの方に質問したところ、WebのGUIは非エンジニアのためのもので、Webのコンソール画面からアイコンを指定したり、自由にUIをカスタムできるようにすることは、優先度が低いみたいです。。

#手順
**1. [Firebase Console](https://console.firebase.google.com/)で新規プロジェクトを作成**
<img width="1265" alt="スクリーンショット 2016-07-02 21.59.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/e02c3015-6681-cf84-240c-8216d4f02bb3.png">

**2. AndroidアプリにFirebaseを追加を選択**
<img width="1278" alt="スクリーンショット 2016-07-02 22.14.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/537bef7a-52af-bd2c-5c83-86e981fb8f11.png">

**3. パッケージ名の入力→google-services.jsonを取得**
<img width="1279" alt="スクリーンショット 2016-07-02 22.14.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/ab0ced13-53ea-7198-a770-b40e33878c1e.png">
<img width="1267" alt="スクリーンショット 2016-07-02 22.15.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/309f7fc3-d562-f8ab-a946-83d3ec5a2047.png">

**4. 歯車マーク/クラウド メッセージングからサーバーキーを取得**
<img width="1276" alt="スクリーンショット 2016-07-02 22.23.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/db3e8879-1f6f-6964-c427-2b8852cc46e1.png">
コンソールでの作業は以上です！

**5. 自アプリでbuild.gradleやFirebaseMessagingServiceやFirebaseInstanceIdService、topicのsubscribe処理などを実装する**

詳しくは[サンプル](https://github.com/u-nation/FCMSample)に書いてみました。(DroidKaigiアプリの通知アイコンを使用させていただきました(>_<))
*google-services.jsonをapp配下に設置するのを忘れずに！*

**6. いよいよFCMを使ってプッシュを配信してみましょう！**
FCMではJsonをhttps://fcm.googleapis.com/fcm/send にPOSTします。notification,dataをそれぞれ単体で使うか、併用するかでバックグラウンド時とフォアグラウンド時で挙動が変わります。こちらの記事が詳しくて最高です。

[Firebase Cloud Messagingで通知をカスタマイズ(Android)](http://starzero.hatenablog.com/entry/2016/05/29/163750)

*個人的にはdataのみを使うとバックグラウンドでもフォアグラウンドでもFirebaseMessagingServiceで処理ができ、GCMと同じようなことができるのでオススメします。*それぞれ実際に挙動の違いを見てみるといいかもしれません。
挙動の違い:[About FCM Message](https://firebase.google.com/docs/cloud-messaging/concept-options#messages-with-both-notification-and-data-payloads)
Jsonに指定する値:[Firebase Cloud Messaging HTTP Protocol](https://firebase.google.com/docs/cloud-messaging/http-server-ref)

POSTするJsonの例

```json:notification単体の例
{
    "to": "/topics/all",
    "notification": {
        "title": "FCM使ってみよう",
        "body": "今日もいい天気ですね",
        "icon": "ic_stat_notification",
        "color": "#ffa714",
        "click_action": "OPEN_ACTIVITY"
    }
}
```

```json:data単体の例
{
    "to": "/topics/all",
    "data": {
        "title": "FCM使ってみよう",
        "body": "今日もいい天気ですね"
    }
}
```

```json:併用の例
{
    "to": "/topics/all",
    "notification": {
        "title": "FCM使ってみよう",
        "body": "今日もいい天気ですね",
        "icon": "ic_stat_notification",
        "color": "#ffa714",
        "click_action": "OPEN_ACTIVITY"
    },
    "data": {
        "title": "FCM使ってみよう",
        "body": "今日もいい天気ですね"
    }
}
```

では実際にPOSTしてみましょう

```curl:curlの場合
curl --header "Authorization: key=あなたのサーバーキー" \
     --header Content-Type:"application/json" \
     https://fcm.googleapis.com/fcm/send \
     -d "{\"to\": \"/topics/all\", \
            \"data\": { \
                \"title\": \"FCM使ってみよう\", \
                \"body\": \"今日もいい天気ですね\" \
            } \
        }"
```

REST clientの場合(DHCのスクショです)
<img width="919" alt="スクリーンショット 2016-07-03 17.51.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/5ea78bd3-a880-fdcd-5497-a6c6348cf6bc.png">


表示例
<img width="691" alt="スクリーンショット 2016-07-03 17.42.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/14760108-2db9-3ed4-e93f-5557ce4f74d1.png">


※ちなみにメッセージを送る際に使用するTopicがコンソール上に反映されるまでは半日から1日かかります。。FirebaseMessaging.getInstance().subscribeToTopic("all");
<img width="679" alt="スクリーンショット 2016-07-02 23.05.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/58939/21e9fa05-5f85-3f7a-10c7-fd422c3bf213.png">

なのでそれまではJsonの"/topics/all"のところをFirebaseInstanceId.getInstance().getToken()で取得したトークンを入れるといいと思います。

#まとめ
•Firebase NotificationsじゃなくてFCMを使う
•Payloadsはdataがオススメ