😎

[FCM] プッシュ通知, チャット, デバイス(ユーザー)間で送り合う

2024/07/02に公開
1

そもそもプッシュ通知っていろんな種類ある

要件 配信方法
1つの端末が1つの端末に送信 チャット node環境での配信, Firebase functions
1つの端末が複数の端末に送信 グルチャ node環境での配信, Firebase functions
1つのトピックをサブスクしている端末らに送信 コミュニティ, 掲示板 node環境での配信, Firebase functions
運営側が複数の端末に送信 キャンペーンの配信, サービスコンテンツの配信 Firebase Admin SDK, FCM HTTP v1 API

送信側と受信側で実装が全く異なる

Firebase Cloud Messaging

FCM の実装には、送信と受信のために以下の 2 つの主要コンポーネントが含まれています。

  • メッセージの作成、ターゲティング、送信を行う Cloud Functions for Firebase やアプリサーバーなどの信頼できる環境。
  • 対応するプラットフォーム固有のトランスポート サービスを介してメッセージを受信する Apple、Android、またはウェブ(JavaScript)クライアント アプリ。

送信側のTL;DR (忙しい人のための"結論")

FCM API(HTTP v1) vs Cloud Functions

①Cloud Functions の利用例

  • データベースの特定の値が更新されたら、プッシュ通知を送る
  • ユーザがアカウントを削除したことを検知して、削除されたユーザに関連するデータをデータベースから削除する
  • その他サービス固有の API を作成する

②GoogleAPI: Firebase Cloud Messaging (HTTP v1) API

RESTで書ける

FCM API(HTTP v1)を検証してみる

Bearer Tokenの(かんたんな)取得の仕方

Node.js: Firebase Admin SDK使ったほうが手っ取り早い?

FCM サーバーとの対話には Firebase Admin SDK または基本的なプロトコルの 2 つの方法があり、どちらを使用するか決定する必要があります。一般的なプログラミング言語で広くサポートされていること、認証や認可を簡単に処理できることから、Firebase Admin SDK を使用することをおすすめします。

functionsを使うパターン

初期package.json
{
  "name": "functions",
  "scripts": {
    "lint": "eslint --ext .js,.ts .",
    "build": "tsc",
    "build:watch": "tsc --watch",
    "serve": "npm run build && firebase emulators:start --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "18"
  },
  "main": "lib/index.js",
  "dependencies": {
    "firebase-admin": "^11.8.0",
    "firebase-functions": "^4.3.1"
  },
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.12.0",
    "@typescript-eslint/parser": "^5.12.0",
    "eslint": "^8.9.0",
    "eslint-config-google": "^0.14.0",
    "eslint-plugin-import": "^2.25.4",
    "firebase-functions-test": "^3.1.0",
    "typescript": "^4.9.0"
  },
  "private": true
}

functions/index.js

functions/index.js
import {onRequest} from 'firebase-functions/v2/https';
import functions from 'firebase-functions';
import admin from 'firebase-admin';
admin.initializeApp();

export const pushTo = onRequest({ region: 'asia-northeast1' }, (request, response) => {
  const title = request.query['title']; // 通知のタイトル
  const body = request.query['body']; // 通知の内容
  const token = request.query['token']; // 送り先のトークン

  // 通知の内容を作る処理
  const message = {
    notification: {
      title: title,
      body: body,
    },
    data: {
      title: title,
      body: body,
    },
    android: { // androidの設定
      notification: {
        sound: 'default',
        click_action: 'FLUTTER_NOTIFICATION_CLICK',
      },
    },
    apns: { // iOSの設定
      payload: {
        aps: {
          badge: 1,
          sound: 'default',
        },
      },
    },,
    "webpush": {
      "headers": {
        "Urgency": "high"
      },
      "notification": {
        "body": "This is a message from FCM to web",
        "requireInteraction": "true",
        "badge": "/badge-icon.png"
      }
    },
    token: token,
  };
  pushToDevice(token, message); // push通知を送る関数に内容を載せて実行
});

// push通知を送る関数
/**
 * @param token
 * @param payload
 */
function pushToDevice(token, payload) {
  admin.messaging().send(payload)
    .then((_pushResponse) => {
      return {
        text: token,
      };
    })
    .catch((error) => {
      throw new functions.https.HttpsError('unknown', error.message, error);
    });
}

なにこれ。

すんなり、いけてもたやないの。。。

(TypeScriptにするといろいろterminalがうるさいのでJsで良さそうだよ♡)