はじめに
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}')
はセキュリティルールと同じくワイルドカードをつかっています。
onCreate
はfirestore
にデータが保存されたのをトリガーに{}
内の処理を実行します。
context.params.userID
はワイルドカードで指定したドキュメントIDを取得します。
userID
がワイルドカードと同じでないとエラーになり思ったような処理ができません。
私はここでめっちゃ詰まってました。
userRef.get()
でドキュメントを取得し、data()
でデータを取得します。
今回の場合
then((user) => {
const userData = user.data();
}
この部分です。
JavaScript
ほぼ触ったことないけどthen
てcathc
あるし、例外処理?と思いながら書いてました。違ってもボコスカに叩かないでくださいね。
調べていないので。
ここまでで保存された時に何かできる状態になりました。
あとは通知を送信するだけですね。
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にてメッセージをください。