ぬまろぐ

←戻る

【PWA】FCMのPUSH通知の種類とハンドリングの実装方法

2023/03/18

FCM(Firebase Cloud Messaging)を使ったプッシュ通知には通知メッセージ(notification)とデータメッセージ(data)の2種類の方法があります。また、アプリ側のハンドリング方法もSDKを利用する方法と標準的なpushイベントリスナの2つの方法があるため、それぞれ紹介していきたいと思います。

img

通知とハンドリングイメージ

1. FCMの通知の種類

FCMのPUSH通知には 通知メッセージ(notification)とデータメッセージ(data) の2種類あります。 通知メッセージは実装不要で楽に通知表示してくれて、データメッセージはハンドリング処理を使って独自に実装できるカスタマイズ性のある通知といった感じです。

1-1. 通知メッセージ(notification)

firebaseで通知メッセージを送るとアプリのハンドリングを行わなくても、firebase SDKが自動的に通知を端末に表示してくれます。(バックグラウンドの場合のみ)

「title」「body」「icon」「image」は使えましたが、「action」や「badge」は使えませんでした。

決まった項目しか使えず自由度は低いので、badgeやactionなどを指定したい場合はデータメッセージを利用します。 とりあえず簡単に通知を送りたい場合には良いかと思います。

1-2. データメッセージ(data)

任意のデータを送ることができ、アプリ側でハンドリングを行い通知を表示します。 自由に処理を作れるので、badgeを使う場合やハンドリングで独自の処理(モニタリング等)を行う際はこちらを利用します。

1-3. データサンプル

FCMでメッセージを送信する際のJSONは以下のようになります。”notification”内のデータが通知メッセージになり、”data”内のデータがデータメッセージになります。 両方指定すると、通知が2通表示されたりします。

{
    "name": "pwa_push_test",
    "notification": {
        "title": "notification title2",
        "body": "notification body2",
        "icon": "./logo.png",
        "image": "./image.png"
    },
    "data": {
        "message": "data message2",
        "title": "data title2",
        "tag": "message-test-2"
    }
}

2. 通知のハンドリング方法

データメッセージを使う場合は、アプリ(javascript側)でハンドリングを行う必要があります。

通知のハンドリングにはFCMのSDKを使ったハンドリングと、PUSHイベントをハンドリングする標準的な方法があります。いろいろ検証した結果、標準的な方法がの方が使いやすいかったです。

2-1. FCMのSDKを使ったハンドリング

FCMのSDKを使ったハンドリングはフォアグラウンドとバックグラウンドの2つ実装が必要です。 フォアグラウンドは、サイトのjavascriptで実装し、サイトを画面に表示中にメッセージを受信した場合の処理を記述します。 バックグラウンドはサービスワーカで実装し、サイトを表示していない時に通知を受信した時の処理を記述します。

2-1-1. フォアグラウンド

フォアグラウンドのハンドリング処理のサンプルは以下のようになります。

import { initializeApp } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-analytics.js";
import { getMessaging, getToken, onMessage } from "https://www.gstatic.com/firebasejs/9.1.0/firebase-messaging.js";

const firebaseConfig = {...}; //内容は省略
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(this.app);
// フォアグラウンド処理のサンプル。通知を表示する処理
onMessage(messaging, (payload) => {
  console.log('[FRONT]Message received. ', payload);
  navigator.serviceWorker.ready.then(function (registration) {
    const notificationTitle = payload.data.title;
    const notificationOptions = {
      body: payload.data.message,
      tag: payload.data.tag,
      icon: './logo.png',
      badge: './badge.png',
      image: './image.png',
      vibrate: [300, 100, 100, 100, 300],
      actions: [{
        action: 'action1',
        title: 'アクション1'
      }
    ]
  };

  registration.showNotification(notificationTitle,
    notificationOptions);
  });
});

2-1-2. バックグラウンド

サービスワーカーのバックグラウンドのハンドリングは以下のようになります。onBackgroundMessageを利用してハンドリング処理を登録します。

importScripts('https://www.gstatic.com/firebasejs/9.1.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.1.0/firebase-messaging-compat.js');

firebase.initializeApp({...}); //省略
const messaging = firebase.messaging();

// バックグラウンド通知のハンドリング
messaging.onBackgroundMessage(function (payload) {
  const notificationTitle = payload.data.title;
  const notificationOptions = {
    body: payload.data.message,
    tag: payload.data.tag,
    icon: './logo.png',
    badge: './badge.png',
    image: './image.png',
    vibrate: [300, 100, 100, 100, 300],
    actions: [{
      action: 'action1',
      title: 'アクション1'
    }
    ]
  };

  self.registration.showNotification(notificationTitle,
    notificationOptions);
});

2-2. FCMのSDKを使わない標準の通知ハンドリング処理

FCMのSDKを利用すると、フォアグラウンドとバックグラウンドで2つ実装したりと結構面倒でした。標準的なPUSH通知のハンドリングを行えば、バックグラウンドもフォアグラウンドもどちらもサービスワーカーの1つのハンドリング処理で実装できるので、こちらの方法も紹介します。

pushイベントのリスナを登録することで実装できます。また、Web画面を開いていても閉じていてもこのイベントは呼ばれるため、実装もこの1か所で良くなります。

// 通知を受けとると push イベントが呼び出される。
self.addEventListener('push', function (payload) {
var data = {};
  if (payload.data) {
    data = payload.data.json();
  }
  const notificationTitle = data.data.title;
  const notificationOptions = {
    body: data.data.message,
    tag: data.data.tag,
    icon: '/abacus/test/logo.png',
    badge: '/abacus/test/badge.png',
    image: '/abacus/test/image.png',
    vibrate: [300, 100, 100, 100, 300],
    actions: [{
      action: 'action1',
      title: 'アクション1'
    }
    ]
  };

  const notificationPromise = self.registration.showNotification(notificationTitle,
    notificationOptions);

  payload.waitUntil(notificationPromise);

}, false)

まとめ

通知にはnotificationとdataの2種類があり、ハンドリング方法にもSDKを利用する方法と標準的な方法の2種類がありますといった話。

個人的にはdataで通知して、ハンドリングは標準的なpushのイベントリスナで実装するのがベストだと思います。