Push通知を実装するために、Firebase Cloud Messaging が使われています。
https://firebase.google.com/docs/cloud-messaging?hl=ja
Flutterのドキュメント
https://firebase.google.com/docs/cloud-messaging/flutter/client?hl=ja
Push通知の実装では、主に4つの機能を実装する必要があります。
通知の権限許可をとる
FCMトークンを取得する
フォアグラウンドでの通知を監視する
バックグラウンドでの通知を監視する
Skimieでは、Push通知関連の機能をStateNotifierで管理しています。
packages/skimie/lib/services/messaging/messaging_provider.dart
参考にしたレポジトリ:
https://github.com/altive/flutter_app_template/tree/main/packages
/// 通知権限の確認
Future<void> requestPermission() async {
// Androidの場合
if (Platform.isAndroid) {
await _flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()!
.requestNotificationsPermission();
}
// IOSの場合
if (Platform.isIOS) {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
return _messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
});
}
// stateの更新
await refetchSettings();
}
通知の権限を確認します。
// デバイスに一意のFCMトークンを登録する
// - ログイン後の画面で実施すること
// - idToken は変わる場合があるらしいため、ウォッチして変わったら更新すること
Future<void> saveFcmToken() async {
final fcmToken = await _messaging.getToken();
Log.i('FCM Token: $fcmToken');
if (fcmToken == null) return;
try {
final deviceService = DeviceService();
await deviceService.save(fcmToken);
} catch (e) {
Log.e(e.toString());
}
}
// FCMトークンの変更を監視する
void tokenRefreshListen() {
final deviceService = DeviceService();
try {
_tokenStream = _messaging.onTokenRefresh.listen(
(fcmToken) async {
await deviceService.save(fcmToken);
},
);
} catch (e) {
Log.e(e.toString());
}
}
FCMトークンを取得します。このトークンは変更される可能性があるので、変更を監視し、
変更があった場合には、再度登録し直す様にしています。
/// 通知を監視する
Future<void> notificationListen(BuildContext context) async {
FirebaseMessaging.onMessage.listen(
(RemoteMessage message) {
final text = message.notification?.body ?? '';
showNotificationToast(
context,
text: text,
onPressed: () {
debugPrint("OnPressed.");
},
);
},
);
}
フォアグラウンドでの、通知を監視している。通知を受け取った場合にlisten 以下が発火し、
showNotificationToastに、通知のメッセージを渡して、実行している。
/// バックグランド設定
void onBackgroundMessage() {
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}
// バックグランドで受け取った通知の処理
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
final notification = message.notification;
Log.i('PUSH Message(Back Ground): ${notification?.body}');
}
アプリが閉じている時の通知を監視している。
1〜4の処理は、通知を初期化する関数で、実行されるようになっている。
https://zenn.dev/flutteruniv_dev/articles/flutter_push_notification?redirected=1
(古くなっている可能性もあります、最新を確認してください。)
通知アイコンの変更
https://qiita.com/mkosuke/items/45dd14c61b633efcfd17
https://firebase.google.com/docs/cloud-messaging/android/topic-messaging?hl=ja#edit-the-app-manifest