【Flutter大学コラボ】受託案件にて利用した
Flutterの技術事例を語る会
Firebase Cloud Messagingを
使用したお知らせプッシュ通知機能
※このページは削除して構いません
USE TEMPLATE
Click
ドコドア株式会社 engineering team 堀田 誠
● 新潟にいます📍
● Flutterエンジニアとして2022年6月にジョイン
● Flutter歴 1年未満
● クロスプラットフォームで幅広く活躍できる Flutterに興味津々
● Widgetによる直感的なレイアウト実装を実現しているところもお気に入り
Flutterを通じて、様々なプロダクトに貢献していきたいです🙌
わたし自身のこと
2
Firebase Cloud Messaging を使用したプッシュ通知機能
● 「お気に入り設定をしたユーザーにプッシュ通知を送信する」機能
● 構成図 / 使用した技術
● 【アプリサイド】Flutter Application / Firebase Firestore
○ FCMの通知許可設定
○ お気に入り設定する機能
● 【サーバーサイド】Flutter for Web / Firebase Functions
○ (お気に入りを参照して)通知するユーザーの FCMトークン取得
○ プッシュ通知の送信処理
お伝えすること
3
実現したいこと
● 通知を開封してアプリで詳細を確認してほしい
● ユーザーの興味があるジャンルの情報を伝えたい
○ ユーザーごとにお気に入りを登録
○ 対象のユーザーにプッシュ通知を送信
「お気に入り設定をしたユーザーにプッシュ通知を送信する」機能
4
とは?
使用した技術
・Flutter for WEB
・Firestore
・Cloud Functions(Node.js)
・Pub/Sub
・Cloud Messaging
・Flutter Application
構成図
5
● Flutter で FCMを利用するために必要なパッケージ
○ firebase_messaging パッケージ
○ flutter pub add firebase_messaging
Firebase Cloud Messaging(FCM)
6
【アプリ側】
受け取りたいお知らせを
お気に入り設定する機能
まずは
受け取りたいお知らせを
お気に入り設定する機能
ここの機能
8
requestPermission()
alert : 通知を表示できるかどうか
badge : アプリアイコンにバッジ数や
通知ドットを表示するか
sound : 通知が表示された時にサウ
ンドを再生するかどうか
参照)
FlutterFire Permissions
https://firebase.flutter.dev/docs/messagin
g/permissions/
Flutterアプリでメッセージを受信する
https://firebase.google.com/docs/cloud-me
ssaging/flutter/receive
FCMの通知許可設定 FirebaseMessaging messaging =
FirebaseMessaging.instance;
NotificationSettings settings = await
messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
9
update()メソッドを使用して、
Firestoreのuserコレクションを
更新している。
※後述の
プッシュ通知を配信すべき対象者の
抽出に使用します💡
参照)
cloud_firestoreパッケージ
https://pub.dev/packages/cloud_firestore
お気に入りを設定する final _db = FirebaseFirestore.instance;
final _collectionPath = 'user';
_db.collection(_collectionPath)
.doc(user.id).update(
{
UserField.favoriteGekidanIdList:
user.favoriteGekidanIdList,
UserField.favoriteLocationIdList:
user.favoriteLocationIdList,
UserField.updatedAt:
Timestamp.fromDate(DateTime.now()),
},
);
10
【管理画面】
お気に入り設定しているユーザーに
プッシュ通知を送信する機能
次に
お気に入り設定している
ユーザーに
プッシュ通知を送信する機能
・通知FCMトークン取得
・送信処理
ここの機能
12
● Node.js で実装
● Pub/Sub トリガーを利用し、一定の間隔で発火
○ お知らせの作成 → トリガー → 未送信のお知らせを検知 → プッシュ通知の送信
○ プッシュ通知を送信したお知らせは、送信済みフラグを立てる
○ functions.pubsub.schedule('your schedule').onRun((context))
○ https://firebase.google.com/docs/functions/schedule-functions
● Cloud Functionsにデプロイ
○ firebaseコマンドを使用して特定の関数だけをデプロイすることも可能
○ firebase deploy --only functions:{デプロイしたい関数名 }
○ https://firebase.google.com/docs/functions/manage-functions
Cloud Functions for Firebase の実装
13
FCMトークン取得
Node.jsとTypeScriptを使用
Firestoreのuserコレクションからお
気に入り設定をしている userドキュメ
ントを取得
userドキュメントから
FCMトークンの配列を取得
→ 取得したFCMトークンにプッシュ
通知を送信します
import * as admin from 'firebase-admin'
export const createPushNotificationDestination = async (
gekidanId: string,
): Promise<string[]> => {
const subscribers = await admin
.firestore()
.collection('user')
.where(
'favoriteGekidanIdList',
'array-contains',
gekidanId
)
.get()
const tokens: string[] = subscribers.docs.map(
(user) => user.data()['fcmToken'],
)
return tokens
}
14
MulticastMessageを作成
tokens : FCMトークンの配列
data : 通知に持たせる値
端末で通知を開いた時にアプリに渡
す値を指定できる
sendMulticast() :
複数のトークンに送信を行える
最大 500 の制限がある
参照)
データメッセージ
https://firebase.google.com/docs/cloud-me
ssaging/concept-options?hl=ja
複数のデバイスにメッセージを送信する
https://firebase.google.com/docs/cloud-me
ssaging/send-message
送信処理 import * as admin from 'firebase-admin'
const pushMessage: admin.messaging.MulticastMessage = {
notification: notificationContent, // プッシュ通知のデータ
tokens: tokens,
android: {
// android用のオプション
},
apns: {
// iOS用のオプション
},
data: {
type: type,
documentId: documentId,
},
}
await admin
.messaging()
.sendMulticast(pushMessage)
.then((response) => {
// 送信に成功した時の処理
})
.catch((error) => {
// 送信に失敗した時の処理
}) 15
【アプリ側】
プッシュ通知を受け取った時の処理
最後に
通知を受け取った時の処理
・通知のデータを確認して
お知らせ画面の表示
ここの機能
17
プッシュ通知を開いた時
の画面遷移処理
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
messageHandler(context, message);
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage
message) async {
messageHandler(context, message);
});
Future<void> messageHandler(BuildContext context,
RemoteMessage message) async {
String messageType = message.data['type'];
String documentId = message.data['documentId'];
// データを参照して、お知らせ画面に遷移する処理
}
・通知を開いた時のハンドラーを指
定する
getInitialMessage().then()
onMessageOpenedApp.listen()
・RemoteMessage.data
送信処理で指定した値
・参照して遷移処理を実装
18
今回の開発中につまずいた点
・ひとつのお知らせに対してプッシュ通知が 2件届いた
→ 送信済みフラグの処理中に次のトリガーが起きてしまたっため間隔を調整した
・端末がアプリをフォアグラウンドで実行している時、通知が表示されない
→ プッシュ通知とは別にアプリ内通知機能が必要になるが、今回は実装していない
・プッシュ通知が必ず、100%、端末に届くというわけではない
→ 端末の設定やネットワーク環境に依存する
→ プッシュ通知の未達 /遅延問題は大手メッセージアプリでも課題としている
→ 対応可能な範囲を把握した上で開発が必要になる
プッシュ通知開発で気をつけたいこと
19
💡実現できたこと
・アプリを開いていないユーザーにもアクションを起こすことができる
・通知を送信する対象者を絞ることで、目的に応じた通知を送信できる
🤔課題
・トリガーの制御、端末の状態、送信処理の検証が大切
・通知を開封した時の画面遷移、アプリアイコンのバッジの表示など、
(今回、お伝えできませんでしたが)要件によっては調整が必要になる
実現できたこと / 課題
20
📗参照したドキュメント
21
Firebase Cloud Messaging[Firebase]
https://firebase.google.com/docs/cloud-messaging/
CloudFunctions[Firebase]
https://firebase.google.com/docs/functions/
cloud_firestore[pub.sub]
https://pub.dev/packages/cloud_firestore
Firebase Cloud Messaging[FlutterFire]
https://firebase.flutter.dev/docs/messaging/overview
こちらご確認ください 😺
お話はここまでです
ありがとうございました🙇
22
Q. pub/subとcloud schedular は何が違いますか?
cloud schedularのスケジューリングをpub/subが読み取りfunctionsをトリガーしている関係になるようです。
参照)Pub/Sub を使用して Cloud ファンクションをトリガーする
https://cloud.google.com/scheduler/docs/tut-pub-sub?hl=ja
Q. 画面遷移の処理はどこに書きますか?main.dart?
プッシュ通知の開封からアプリが起動されたことを検知するために、
起動した時に必ず実行される場所に書く必要があります。main.dartも良いと思います。
遷移の処理の内容は画面遷移の設計に気をつけています。
Q&A ※2022/12/16 追記
23

Firebase Cloud Messagingを使用したお知らせプッシュ通知機能.pdf