【FCM】AndroidのChannel管理の際にハマった話


概要

実装したかったことはAndroidアプリ開発にてPush通知を受け取る際にChannelを作成し、管理をすることです。サーバーからFCM経由でクライアントに送信する。FCMについての知識がなかったことが原因でハマったことについて書きます。

ハマったこと

ハマったことは以下の2点です。

  • ChannelIDを振り分けているはずなのに上手く通知されない
  • BackgroundのときPush通知が届かない

簡単に...

FCMとは?

FCM(FirebaseCloudMessaging)はFirebaseで提供されているメッセージを送ることができるサービスである。できることは以下の通り。

  • 通知メッセージ・データメッセージの送信
  • メッセージ配信する際のターゲット設定
  • クライアントアプリからのメッセージ送信

Channelとは?

Android8.0から通知は全てChannelに割り当てることが必要になった。Channelのおかげでより細かく通知の受け取りON/OFFを指定できる。

通知チャネルを作成して管理する | Android Developers

データメッセージと通知メッセージ

今回ハマったことを解決するためには「データメッセージ」と「通知メッセージ」を理解する必要があった。

通知メッセージ

Backgroundで通知を受け取りたいときは通知メッセージを使う。アプリの実装を介さずにFCM SDKで自動処理し、通知トレイに届き、デバイスにメッセージを表示する。Foreground時はコールバック関数で処理をする。

データメッセージ

Foreground時にアプリ内で処理できるもの。コールバック関数にてデータペイロードを受信する。

メッセージを受信した時の処理

  • Backgroundの場合
    • 通知トレイにて通知ペイロードのみを受け取り、Foregroundに入った時にデータペイロードを処理する
  • Foregroundの場合
    • どちらも受信し処理する

FCM メッセージについて | Firebase

結論

通知が予期したChannelに割り振られない

サーバからFCMにデータを送る際に、 ChannelIdも一緒に指定する。

うまくいかなかった原因としてはクライアントでChannelを作成しただけだった。Foregroundの時にはデータ通知としてアプリ内ロジックを通るため、指定されたChannelに割り振られるが、Backgroundの際はアプリ内ロジックを通らないため、サーバからFCMに送る時点で ChannelIdを指定する必要がある。

Backgroundのときそもそも通知が届かない

上記の通り通知メッセージを使わないと通知が届かないので注意が必要である。

Chips

「その他」や "Miscellaneous"というChannelが勝手に生成されている

自分で設定した覚えのない「その他」(英語だと"Miscellaneous")というChannelがあり、全ての通知がそこに割り振られていた。独自で追加したChannelのOn/Offを切り替えても意味のない状態。

 登録されているChannelを取得できるメソッドがあるので調査をしたら、以下のログが撮れた。

~~~省略~~~
D/mydebug: getChannels[1]: 
NotificationChannel{
 mId='fcm_fallback_notification_channel', 
 mName=Miscellaneous, 
 mDescription=, 
 mImportance=2, 
 // 省略
}
~~~省略~~~

mIdが 'fcm_fallback_notification_channel'となっていることより、何らかが原因でFCM側で生成されているものだと発覚した。

もし予期せぬ ChannelIdがクライアントに送られてきた場合に「その他」ではなく自分で生成した「全般」や「その他」といったChannelに割り振りたい場合はAndroidManifest.xmlに以下のように meta-dataを追加して自分で ChannelIdを指定する。

<meta-data
    android:name="com.google.firebase.messaging.default_notification_channel_id"
    android:value="@string/default_notification_channel_id" />

valueは @string/default_notification_channel というKeyにしてあげないと動かなかった。自由に命名したら動かなかったのでメモです。不安なのでもし動いたら教えてください。

まとめ

Foreground / Backgroundで処理の内容を変えたりするには、上手く通知メッセージ / データメッセージを理解する必要がある。少々複雑と感じるかもしれないが、ドキュメントも分かりやすいので、丁寧に理解して実装すれば非常に便利ですね。