1. flutter_local_notifications 패키지 추가

pubspec.yaml 파일에 다음을 추가합니다:

dependencies:
  flutter_local_notifications: ^latest_version
  firebase_messaging: ^latest_version

2. flutter_local_notifications 초기화

import 'package:flutter_local_notifications/flutter_local_notifications.dart';

// 로컬 알림 설정
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // 백그라운드 메시지 처리
  await Firebase.initializeApp();
  print("Handling a background message: ${message.messageId}");
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  // 백그라운드 메시지 핸들러 등록
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  // 로컬 알림 초기화
  const AndroidInitializationSettings initializationSettingsAndroid =
      AndroidInitializationSettings('@mipmap/ic_launcher');
  const InitializationSettings initializationSettings = InitializationSettings(
    android: initializationSettingsAndroid,
  );
  await flutterLocalNotificationsPlugin.initialize(initializationSettings);

  runApp(MyApp());
}

// 포그라운드 메시지 처리 및 로컬 알림 표시
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  print("Foreground message received: ${message.notification?.title}");

  // 알림 표시
  _showNotification(
    message.notification?.title ?? 'No Title',
    message.notification?.body ?? 'No Body',
  );
});

// 로컬 알림 표시 함수
Future<void> _showNotification(String title, String body) async {
  const AndroidNotificationDetails androidPlatformChannelSpecifics =
      AndroidNotificationDetails(
    'default_channel', // 채널 ID
    'Default', // 채널 이름
    importance: Importance.max,
    priority: Priority.high,
    showWhen: false,
  );

  const NotificationDetails platformChannelSpecifics =
      NotificationDetails(android: androidPlatformChannelSpecifics);

  await flutterLocalNotificationsPlugin.show(
    0, // 알림 ID
    title, // 알림 제목
    body, // 알림 내용
    platformChannelSpecifics,
  );
}

FCM에서 foreground 에서의 알림은 flutter_local_notifications 를 이용해서 별도로 처리 해주어야 한다.

만약 알림창의 커스텀을 원할 경우

1. Android에서 알림 커스터마이징

dart
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

void showCustomNotification() async {
  const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
    'custom_channel_id', // 채널 ID
    'Custom Notifications', // 채널 이름
    channelDescription: 'This channel is for custom notifications',
    importance: Importance.max,
    priority: Priority.high,
    ticker: 'Custom Ticker', // 상태 표시줄 텍스트
    color: Color(0xFF123456), // 알림 아이콘 색상
    enableLights: true, // LED 사용
    ledColor: Color(0xFF00FF00), // LED 색상
    ledOnMs: 1000, // LED 켜짐 지속 시간
    ledOffMs: 500, // LED 꺼짐 지속 시간
    enableVibration: true, // 진동 허용
    vibrationPattern: Int64List.fromList([0, 500, 1000, 500]), // 진동 패턴
    playSound: true, // 소리 재생 여부
    sound: RawResourceAndroidNotificationSound('custom_sound'), // 커스텀 소리
    styleInformation: BigTextStyleInformation(
      'This is a custom notification with a longer description. You can customize this!',
      bigText: 'Here is an expanded notification for additional details.',
    ),
  );

  const NotificationDetails platformDetails = NotificationDetails(
    android: androidDetails,
  );

  await flutterLocalNotificationsPlugin.show(
    0, // 알림 ID
    'Custom Notification Title', // 알림 제목
    'This is the body of the custom notification.', // 알림 본문
    platformDetails,
  );
}

2. iOS에서 알림 커스터마이징

dart
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

void showIOSNotification() async {
  const DarwinNotificationDetails iosDetails = DarwinNotificationDetails(
    badgeNumber: 1, // 앱 아이콘 배지 번호
    presentAlert: true, // 알림창 표시 여부
    presentSound: true, // 사운드 재생 여부
    presentBadge: true, // 배지 표시 여부
    sound: 'custom_sound.aiff', // 커스텀 사운드 (iOS 프로젝트에 추가 필요)
    subtitle: 'Custom Subtitle', // 서브타이틀
    threadIdentifier: 'thread_id', // 알림 그룹화
  );

  const NotificationDetails platformDetails = NotificationDetails(
    iOS: iosDetails,
  );

  await flutterLocalNotificationsPlugin.show(
    1, // 알림 ID
    'iOS Custom Notification', // 알림 제목
    'This is the body of the iOS custom notification.', // 알림 본문
    platformDetails,
  );
}