4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Cloud FunctionsでFirestoreの更新を特定のデバイスにpush通知する

Last updated at Posted at 2020-02-17

Cloud Functions × Firestore × Firebase Cloud Messaging

Cloud Functionsはサーバレスコンピューティングサービスです。様々なイベントをトリガーにしてアクションを実行することができ非常にコストパフォーマンスに優れています。

今回はこのCloud Functionsを用いてFirestoreにデータが追加されたら特定のデバイスにpush通知が届くようにします。

Structure

通知を送信したいDBを設計します。今回は簡略化のためにnotificationsというコレクションにしています。
ここであらかじめテーブルにデバイスのidが紐付いているとやりやすいと思います。

notifications
│
├── notification
│   ├── text
│   └── users
.        ├── bJi8iJLw0ufF1HCO17v3b7UTVS53
.        .
.        .

Architecture

IMG_B2ADF5BEBE4E-1.jpeg

Steps

以下のことが既に完了している前提で実装していきます。多分この記事にたどり着くような人はコーディングで行き詰まった人だと思います。Firestoreのサンプルがここしかなかった。。。

  • Firebaseプロジェクトは作成済み
  • 必要なパッケージはインストール済み
  • クライアント側のリモート通知設定済み

1. Cloud Functionsをスタートする

まずプロジェクトを作成します

$ Firebase init

functionsディレクトリ内にあるindex.jsにコードを記述していきます。

2. コードを記述

index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.sendNotifications = functions.firestore.document('notifications/{notificationId}').onCreate(
    async (snapshot) => {
        // Notification details.
        const newValue = snapshot.data();

        const payload = {
            notification: {
                title:"新規ライブ",
                body: newValue.text + "の新しいライブが追加されました!",
                content_available: 'true',
                sound: "default",
                click_action: `https://${process.env.GCLOUD_PROJECT}.firebaseapp.com`,
            }
        };

        const userIDs = newValue.users

        // Get the list of device tokens.
        userIDs.forEach(function (value) {
            admin.firestore().collection('fcmTokens').doc(value).get()
                .then(function (querySnapshot) {

                    let fcmToken = querySnapshot.data().fcmToken
                    admin.messaging().sendToDevice(fcmToken, payload);
                    return;
                }).catch(error => { return });
        });
    });

なんやこれポイント

サンプルに const allTokens = await admin.firestore().collection('fcmTokens').get(); ってあったのでてっきりFirestoreのfcmToken勝手にここに格納されてるのかと思いきや自分でDBつくるっぽかった。なので、userIdと紐付けて識別できるようにしました。

fcmTokens
│
├── fcmToken(id: uid)
│   └── fcmToken
.       
.    

まずfunctions.firestore.document()の引数にコレクションを指定します。今回はテーブルに新たなドキュメントが追加されたときに発火するようにしたいのでonCreate()を呼び出しています。
その他にもonUpdate()onDelete()などさまざまなトリガーがあります。詳しくはこちら

そして、payloadに通知の設定をします。

fcmTokensというコレクションからfcmtokenをゲットすることができます。RealtimeDBより便利な気がする。

最後にsendToDevice()で取得したユーザのトークンにまとめてpush通知を送信しています。

3. Deploy

$ firebase deploy

なんか死んでたらログを確認してちょこちょこ直していきましょう。

4. Test

ためしにPythonからFirestoreに新しいドキュメントを追加してみます

import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore


cred = credentials.Certificate()
firebase_admin.initialize_app()
db = firestore.client()

notification_data = {
    "text": "MY FIRST STORY",
    "users": ["gHrdAxQhFYdTmoFjgi8RX8PljXv1"]
}

db.collection(u'notifications').document().set(notification_data)

任意のデバイスにpush通知が来ればオッケー。たっくーTV見てたのは内緒。

IMG_9239.JPG

コードはこちら

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?