1
3

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にデータが保存をトリガーに通知を送信する

Posted at

はじめに

Cloud Messagingで通知を送信できたはいいけど、LINEみたいにメッセージを受信した時に通知を送信するのはどうするのか気になったので調べました。
ちなみにめっちゃたくさんの記事を読み漁りました。
公式のドキュメントも読んだけど、日本語がむずがしい!もっと簡単な日本語にしてくれ!
今回はFirestoreにデータが保存されたときに通知を送信するようにしてみます。

本記事はCloud Messagingにてテスト用の通知の送信はできるところまでセットアップしていることを前提に進めていきます。

また、Cloud Functionsを利用するに当たって料金プランを無料のSparkから従量制のBlazeに変更している必要があります。

AppDelegateの設定

Firebaseの公式にも書いてある通り

func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
}

この関数でトークンをサーバーに送信します。
関数の呼び出しタイミングは公式に以下ように書いています。

・登録トークンが新規の場合、そのトークンをアプリケーション サーバーに送信します。
・登録トークンをトピックに登録します。これは新規登録の場合、またはユーザーがアプリを再インストールした場合にのみ必要です。

トークンは通知を送信する際に必要なので

    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        UserDefaults.standard.setValue(fcmToken, forKey: "fcmToken")
        UserDefaults.standard.synchronize()
    }

と、こんな感じで一時的に保存しておいてfirestoreにユーザーデータを保存する際にtokenも保存しましょう。
swift側のコードはこれだけです。

Cloud Functions

Cloud Functinosの設定をしていきましょう。
※今回はnpmを使うのでnodeとnpmのインストールが必須です。
ターミナルで次のコマンドを順番に入力してください。

npm install -g firebase-tools
firebase login
firebase init

firebase initを入力するとなんか聞かれますが

  • 利用する機能:Functions: Configure and deploy Cloud Functions
  • デフォルトのFirebaseプロジェクト:作成したFirebaseプロジェクトを選択します
  • 言語:JavaScript
  • ESLintを利用するか:N
  • 今すぐ依存関係をインストールするか:Y

このように答えてください。
利用する機能はカーソルを合わせたらEnterではなくSpace->Enterの順に入力してください。

これで作業ディレクトリにfuncionsフォルダなどができています。
できているはずです。
できてるよね...?

次項からJavaScriptを書いていきます。

Index.js

先程できたfunctinonsディレクトリ内にindex.jsというファイルができていると思います。
それを開くと

const functions = require("firebase-functions");

というコードとコメントだけが書かれていると思います。
これはプログラミングによくある おまじない💕 です。
まあこれを書くとfunctionsが使えるよというものなので消さないでください。
おまじないをさらに追加します。

const functions = require("firebase-functions");
// Admin SDKを使うのに必要(おまじない)
以下を追記
const admin = require("firebase-admin");
admin.initializeApp();
const firestore = admin.firestore();

次にプッシュ通知のタイトルやメッセージ内容です。

const pushMessage = (fcmToken, userName) => ({
    notification: {
        title: "保存が完了しました",
        body: `${userName}の保存が完了しました`,
    },
    data: {
        hoge: `fuga`,// 任意のデータをおくれる
    },
    token: fcmToken,
});

jsでは文字列内に変数をねじ込むにはバッククォートなので気をつけてください。

ここまでは正直前座です。
ここから通知を送信するのに必要なコードになります。

コード全体を載せます。

exports.saveUser = functions.firestore
    .document('users/{userID}')
    .onCreate((snapshot, context) => {
        const userID = context.params.userID;
        console.log('ユーザ情報をFirestoreに保存しました. userID: ', userID);
        const userRef = firestore.doc(`users/${userID}`);
        userRef.get().then((user) => {
            const userData = user.data();
            admin.messaging().send(pushMessage(userData.fcmToken, userData.name))
                .then(res=> {
                    console.log('メッセージの送信に成功: ', response);
                })
                .catch(err => {
                    console.log('メッセージの送信に失敗: ', e);
                })
        }).catch(err => {
            console.log("失敗:", err);
        })
    });

解説部いきます。
一行目の
exports.saveUserですがsaveUserがデプロイする関数名です。
exports.{関数名}です。

.document('users/{userID}')はセキュリティルールと同じくワイルドカードをつかっています。

onCreatefirestoreにデータが保存されたのをトリガーに{}内の処理を実行します。

context.params.userIDはワイルドカードで指定したドキュメントIDを取得します。
userIDがワイルドカードと同じでないとエラーになり思ったような処理ができません。
私はここでめっちゃ詰まってました。

userRef.get()でドキュメントを取得し、data()でデータを取得します。
今回の場合

then((user) => {
            const userData = user.data();
}

この部分です。
JavaScriptほぼ触ったことないけどthencathcあるし、例外処理?と思いながら書いてました。違ってもボコスカに叩かないでくださいね。
調べていないので。

ここまでで保存された時に何かできる状態になりました。
あとは通知を送信するだけですね。

admin.messaging().send(pushMessage(userData.fcmToken, userData.name))
                .then(res=> {
                    console.log('メッセージの送信に成功: ', response);
                })
                .catch(err => {
                    console.log('メッセージの送信に失敗: ', e);
                })

これで送信できます。
send(pushMessage(...))で通知のメッセージ内容を渡してあげます。

Deploy

ここまできたら

firebase deploy

とターミナルに入力してください。

そしてfirestoreにデータを保存すると...
きっと通知が来るはずです。

ちなみに

firebase deploy --only functinons:{関数名}

で任意の関数だけdeployできるそうです。

最後に

丸一日(他のこともしていたから実際は5時間くらい)かけてハマりにハマってしまって頭を抱えたcloud functinosでしたが、時間をかけたおかげで自分の中ではなんとか理解できたと思います。
それをしっかりこの記事でアウトプットできているかは別ですが。

普段SwiftばっかりなのでJavaScriptは難しかったです。
この機会にすこし勉強してみようかな。

質問、ご指摘等ございましたら是非コメントやTwitterのDMにてメッセージをください。

1
3
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
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?