こんにちは、Pentagonでアプリ開発している髙谷です。
Flutterでモバイルアプリを開発していると、Push通知を導入する機会が多くあります。FCM(Firebase Cloud Messaging)によるPush通知を受け取るだけでなく、アプリ状態による挙動の違いや通知をタップしたときの処理までを正しく実装するには、いくつかの注意点があります。
本記事では、Flutter開発者に向けて、Push通知の受信とタップ処理に特化した実装方針をご紹介します。iOSとAndroidの違いも踏まえつつ、安定した通知体験を実現しましょう。
【こんな人に読んで欲しい】
- FlutterアプリにPush通知を導入しようとしている
- アプリの状態(フォアグラウンド/バックグラウンド/停止)による通知処理の違いを理解したい
- 通知をタップしたときの処理まで含めて実装したい
【この記事を読むメリット】
- アプリ状態ごとの通知の表示・処理フローが分かる
- iOSとAndroidそれぞれの挙動の違いや実装ポイントがわかる
- 通知タップ時の処理までを網羅した実装方針が身につく
【結論】
FlutterでのPush通知実装は、アプリ状態によって処理を切り分けることと、OSごとに異なる設定・制約への対応が鍵です。
特にAndroidではフォアグラウンド表示を自前で実装する必要があり、通知をタップした際のハンドリングも状態によって異なります。
この記事の前提
- FCM経由でのPush通知受信
- 通知受信と通知タップ処理に特化してご紹介
- エラーハンドリングは省略
- 環境
- Flutter 3.32.5
- firebase_messaging: ^15.2.7
- flutter_local_notifications: ^19.3.0
- permission_handler: ^12.0.0+1
アプリ状態ごとの通知処理の違い
通知の受信やタップ後の処理は、アプリがどの状態にあるかによって挙動が異なります。
アプリの状態 | アプリの状態 | タップ時の処理 |
---|---|---|
フォアグラウンド | iOS:追加設定により表示 Android:自前で表示 |
FirebaseMessaging.onMessageで処理 |
バックグラウンド | OSが自動で表示 | FirebaseMessaging.onMessageOpenedAppで処理 |
停止 | OSが自動で表示 | FirebaseMessaging.instance.getInitialMessage()で処理 |
OSごとの初期化と通知権限のリクエスト
iOSの場合
iOSでは、通知の許可をユーザーから明示的に得る必要があります。また、フォアグラウンドでも通知を表示したい場合は、setForegroundNotificationPresentationOptionsの設定が必要です。
final _messaging = FirebaseMessaging.instance;
await _messaging.requestPermission();
await _messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
Androidの場合
Android 13からは通知権限が必須となっており、permission_handlerを使って明示的に許可を求める必要があります。
await Permission.notification.request();
また、flutter_local_notificationsを使って、フォアグラウンド通知向けのアイコン指定や、通知タップ時の処理の登録ができます。
final _localNotificationPlugin = FlutterLocalNotificationsPlugin();
// 通知チャンネルの作成
const androidChannel = AndroidNotificationChannel(
‘your_channel_id’,
‘your_channel_name’,
importance: Importance.max, // 通知の優先度(Android 8以降)
);
await _localNotificationPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(androidChannel);
// ローカル通知のアイコン設定
const iconName = 'your_icon_name';
const initializationSettings = InitializationSettings(
android: AndroidInitializationSettings(iconName),
);
// ローカル通知の初期化
await _localNotificationPlugin.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (response) {
// タップ時の処理
},
);
}
通知の受信とタップ処理
通知を受け取るためのリスナーや、タップ後の処理をアプリ起動時に設定します。
final _messaging = FirebaseMessaging.instance;
/// アプリがフォアグラウンド状態にあるときの通知リスナーを設定
FirebaseMessaging.onMessage.listen((message) {
// Androidではフォアグラウンド状態の通知表示のため必要
if (Platform.isAndroid) {
// Androidでのフォアグラウンド通知表示(後述)
_showAndroidLocalNotification(message);
}
// タップ時の処理
});
/// アプリがバックグラウンド状態にあるときの通知リスナーを設定
FirebaseMessaging.onMessageOpenedApp.listen((message) {
// タップ時の処理
});
/// アプリが停止状態にあるときの通知リスナーを設定
final initialMessage = await _messaging.getInitialMessage();
if (initialMessage != null) {
// タップ時の処理
}
Androidでのフォアグラウンド通知表示
Androidでは、アプリがフォアグラウンドにあると通知が表示されないため、flutter_local_notificationsを使って自前で表示します。
final _messaging = FirebaseMessaging.instance;
final _localNotificationPlugin = FlutterLocalNotificationsPlugin();
/// Androidのフォアグラウンド状態での通知表示
void _showLocalNotification(RemoteMessage message) {
// 通知内容の取得
final notification = message.notification;
if (notification == null) {
return;
}
// 通知チャンネルの設定
const androidDetails = AndroidNotificationDetails(
‘your_channel_id’,
‘your_channel_name’,
importance: Importance.max,
priority: Priority.max,
);
// ローカル通知の表示
_localNotificationPlugin.show(
notification.hashCode,
notification.title,
notification.body,
const NotificationDetails(android: androidDetails),
payload: json.encode(message.data),
);
}
まとめ
本記事では、FlutterアプリにPush通知を導入する際にまず押さえておくべき「通知の受信からタップ後の処理まで」に特化して解説しました。
通知処理の実装は一見シンプルに見えて、実はアプリの状態やOSごとの制約に応じた考慮が必要です。まずはこの受信処理とタップ処理を正しく実装することで、通知の運用・分析・改善へとつなげていくことができます。