Firebase をいくらか使ってみて感じた、みんなもハマりそうなポイントをメモしておく。
setBackgroundMessageHandler が発火しない
ソースだけ見ていると、payload にサーバーからプッシュで送りたいデータが入っていて、 showNotification で表示させる前にカスタマイズできるところだなと思うのだが、
ここの仕様はちょっと複雑。
messaging.setBackgroundMessageHandler(function(payload) {
console.log(
"[firebase-messaging-sw.js] Received background message ",
payload
);
// Customize notification here
const notificationTitle = "Background Message Title";
const notificationOptions = {
body: "Background Message body.",
icon: "/firebase-logo.png"
};
return self.registration.showNotification(
notificationTitle,
notificationOptions
);
});
setBackgroundMessageHandler never fired · Issue #71 · firebase/quickstart-js
Github の issue に発火しないぞと投稿があるように、
マニュアル通り使っていると setBackgroundMessageHandler が発火することはまずない。
# setBackgroundMessageHandler が発火しない
{
"notification": {
"title": "Background New Topic Title",
"body": "Background New Topic body",
"click_action": "https://firebase.google.com/"
},
"data": {
"id": "hogehoge",
"age": 30
},
"to": "[YOUR-REGISTRATION-ID]"
}
# setBackgroundMessageHandler が発火する
{
"data": {
"title": "Background New Topic Title",
"body": "Background New Topic body",
"click_action": "https://firebase.google.com/",
"id": "hogehoge",
"age": 30
},
"to": "[YOUR-REGISTRATION-ID]"
}
notification フィールドを使ってプッシュ通知で出したい要素を指定していると、setBackgroundMessageHandler を無視して通知が出る仕組みらしい。
解決策
notification フィールドを使わずにすべて data フィールドに入れておくと、setBackgroundMessageHandler が発火される!
Note: If you set notification fields in your HTTP or XMPP send request, those values take precedence over any values specified in the service worker.
(Receive Messages in a JavaScript Client | Firebase)
サーバーから送った値が優先されるのは知っていたが、
setBackgroundMessageHandler 自体が発火されないとは思わなかった。
自前の notificationclick の function が発火しない
notificationclose fired but notificationclick dose not fire · Issue #102 · firebase/quickstart-js
どうにもわからねぇとなって issue まで発行してしまったのだが、
firebase-messaging.js を読み返してたら自己解決した。
importScripts("https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js");
firebase.initializeApp({
messagingSenderId: "xxxxx"
});
const messaging = firebase.messaging();
// not fire
self.addEventListener("notificationclick", function(event) {
console.log("notification open");
// log send to server
});
// fired
self.addEventListener("notificationclose", function(event) {
console.log("notification close");
// log send to server
});
初めはこんな感じで書いていたのだが、
notificationclone は反応するのに notificationclick が反応しない!!
firebase-messaging.js の中を見ると、
同じく notificatoinclick を呼んでいるがこちらは起動している。
T.addEventListener("notificationclick", function (a) {
return ga(b, a)
}, !1);
addEventListener で add って言うくらいだから、
同じ element に対して同じ event type でいけるはずなのになぜ?
もうちょっと読み進めていくと怪しいメソッドを見つける。
(他にも notification.close で element を閉じてしまっているから後続の同 element を使う処理が動いていないのでは?と思ったが検討違いだった)
ga = function (a, b) {
if (b.notification && b.notification.data && b.notification.data.FCM_MSG) {
b.stopImmediatePropagation();
b.notification.close();
Event.stopImmediatePropagation() - Web APIs | MDN
stopImmediatePropagation どうやら多重実行防止のための関数らしい。
これ以降は addEventListener をしていても同じ element と event type のものは実行されない。
解決策
stopImmediatePropagation される前に addEventListener してしまえば、
先に実行されるので、これで自前の notificationclick が発火するようになった!
self.addEventListener("notificationclick", function(event) {
console.log('notification open');
var message = event.notification.data.FCM_MSG;
console.log(message);
// log send to server
});
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': 'xxxxx'
});
const messaging = firebase.messaging();
日本語版のドキュメントは記述が古い
FCM の左メニューを見てもらえれば一目瞭然なのだが、
Web と FCM サーバーだけでもだいぶ違う。
そもそも大項目の時点で Unity とか日本語版はないし。
これのせいで 1 回古い仕様や非推奨の要素使って実装してしまった……
解決策
他の部分も情報が古い&情報自体がないことがあるので、
横着せずに英語版のドキュメントを読みましょう。