1、FCM(Firebase Cloud Messaging)とは
Firebaseが提供しているアプリにプッシュ通知を送る機能です。
機能自体無料で使えて、アプリ側ではfirebaseから取得したfcmトークンをfcmに設定するだけでプッシュ通知を受け取れるためかなり便利です。
本格的なアプリを作るとなるとプッシュ通知は必要不可欠です。
https://firebase.google.com/docs/cloud-messaging?hl=ja
2、FCMの簡単な仕組み・設定方法
https://firebase.google.com/?hl=ja
↑Firebaseでプロジェクトを作成し、左のメニュー欄からCloud Messagingを選択します
開始方法からiOS、Android両方の設定をします。
iOSの方はAPNs認証キーの設定も必要なため、Apple Developerの登録も必要です。
今回はAndroidのみですのでそこは割愛します。
https://rnfirebase.io/messaging/usage
次にアプリ側でFCMトークンを取得し、そのFCMごとに識別して通知が送られてきます。
本題
プロジェクトでFCMを使うことになり、アプリの管理画面から通知文を作成し、APIからFCMにリクエストを出してFCMを経由してアプリに通知が届くような仕様でした。
今回FCMの実装をしている時ににつまずいたことは
・FCMの画面から直接トークンを指定して、送った場合→通知が届き、タップするとアプリが起動する
・アプリの管理画面から通知を送信し、APIからリクエストを出してFCMを経由して送った場合→通知は届くがタップしてもアプリが起動しない
という件でした。
なぜか管理画面から送る通知はタップしても起動することなく、そのまま通知メッセージが消えるだけでした。
原因
FCMから直接送った通知のデータと管理画面でAPIを使って送った通知のデータを見比べてみたところ原因が判明しました。
FCMから返ってくるデータを取得するにはsetBackgroundMessageHandler
を使います。
アプリがバックグラウンドにある状態もしくはキルしている状態の時、プッシュ通知が送られてきた時にFCMからのレスポンスを取得することができます。
以下のコードをindex.jsに追記するとremoteMessageにデータが入っています。
import messaging from '@react-native-firebase/messaging';
messaging().setBackgroundMessageHandler(async remoteMessage => {
console.log('Message handled in the background!', remoteMessage);
});
ちなみにフォアグラウンド状態でも通知のデータを受け取れますが今回は割愛します。
データを比べてみる
1、firebaseでタイトルとテキストを入力、fcm通知を選んで送信
{
"notification": {
"android": {},
"body": "通知本文",
"title": "通知タイトル"
},
"from": number,
"ttl":number,
"sentTime": 1633065375430,
"data": {},
"messageId": "${messageId}",
"collapseKey": "バンドルID"
}
2、管理画面(API)から通知を送信
{
"notification": {
"android": {
"clickAction": "attention"
},
"body": "通知本文"
},
"sentTime": 1633065600374,
"data": {},
"from": "501097458848",
"messageId": "${messageId}",
"ttl": 2419200,
"collapseKey": "バンドルID"
}
管理画面から送った方にはandroidオブジェクト内にclickActionが入っています。
これが原因でした。
https://firebase.google.com/docs/cloud-messaging/http-server-ref?hl=ja
ここのclick_actionのところに記載されているとおり、
ユーザーが通知をクリックしたときに実行されるアクション。 これが指定されている場合、ユーザーが通知をクリックすると、一致するインテント フィルタを持つアクティビティが起動します。
clickActionを指定するとfcmトークンに紐ずくアプリを起動するのではなく、一致するインテントフィルタ(アプリで別途設定する値)に紐ずくアプリを起動させる挙動になります。
今回このインテントフィルタを設定していなかったので一致するインテントフィルタがなく、アプリが起動しませんでした。
ちなみにこのclickActionの使い道ですが、
例えば
1、LINEアプリからプロフィール欄のBGMを設定しませんか?と通知がくる
2、ユーザーがタップするとLINEアプリではなく、LINE MUSICアプリが起動し、すぐ設定が行える
こんな挙動をしたい時は便利かもしれません。
ただ別のアプリを起動させる必要もないため、今回はclickActionは削除する方針にしました。
####clickActionを削除すると問題なくアプリが起動しました!
補足
アプリ起動後、通知があるページ(お知らせ画面)に遷移させたいときは
1、アプリがバックグラウンド状態の時:onNotificationOpenedApp
2、アプリを閉じている状態の時:getInitialNotification
この二つを初期マウント時(useEffect)に走らせればデータを取得できます。
そのデータから通知のidを受け取りそれに紐ずく画面に遷移すれば意図した挙動になるかと思います。