expo-server-sdk
expoPushTokenを使ってクライアント側に通知を送ることができます。
firebase-functions
クラウドサービスの構築と接続に使用するサーバーレスのランタイム環境です。
シンプルで一義的な関数を作成できます。関数の定期実行
が可能です。
Cloud Firestoreに保存されているデータを読み取り通知
今回は1時間毎
に通知を送る仕様で作成します。データ構造は以下のとおりです。
シンプルにするためコレクション名を時間
に、ドキュメント内のデータはexpoPushToken
とbody
の2つとしています。
※クライアント側のexpoPushToken
の取得方法や設定は以下のリンクをご参照ください。
Cloud Functions
かたまり
の意味を持つchunks
に通知の情報をまとめます。
その後、expo.sendPushNotificationsAsync()
により通知を行います。
let chunks = expo.chunkPushNotifications(messages)
;(async () => {
for (let chunk of chunks) {
try {
await expo.sendPushNotificationsAsync(chunk)
} catch (error) {
...
}
}
})()
})
全体のコードです。
index.ts
import * as functions from "firebase-functions"
import * as admin from "firebase-admin"
import { Expo, ExpoPushMessage } from "expo-server-sdk"
admin.initializeApp()
interface DATA {
expoPushToken: string
body: string
}
exports.scheduledFunctionPushNotifications = functions
// 場所
.region("asia-northeast1")
// 頻度:毎時0分 左から「分、時、日、月、曜日」
.pubsub.schedule("0 * * * *")
// タイムゾーン
.timeZone("Asia/Tokyo")
// 主処理
.onRun(async () => {
let expo = new Expo()
// 現在の日本時間を取得
const japanStandardTime = new Date().toLocaleString("ja-JP", {
timeZone: "Asia/Tokyo",
})
const nowHour = new Date(japanStandardTime).getHours().toString()
// 現在の時間と一致する時間名のコレクション内の全データを取得
const snapshot = await admin.firestore().collection(nowHour).get()
const firestoreDatas = snapshot.docs.map((doc) => doc.data() as DATA)
// 通知情報を保存する配列を作成
let messages: ExpoPushMessage[] = []
// コレクション内のデータをfirestoreDataとして一つずつ取得
for (let firestoreData of firestoreDatas) {
let pushToken = firestoreData.expoPushToken
let body = firestoreData.body
// ExpoPushTokenの有効性を確認する
if (!Expo.isExpoPushToken(pushToken)) {
console.error(`Push token ${pushToken} is not a valid Expo push token`)
continue
}
// 一人ひとりの通知情報を保存用の配列に格納
messages.push({
to: pushToken,
sound: "default",
body,
})
}
// 通知
let chunks = expo.chunkPushNotifications(messages)
let tickets = []
;(async () => {
for (let chunk of chunks) {
try {
let ticketChunk = await expo.sendPushNotificationsAsync(chunk)
console.log(ticketChunk)
tickets.push(...ticketChunk)
} catch (error) {
console.error(error)
}
}
})()
})