<aside> 💡 파이어베이스 유틸 클래스의 경우 메인화면에서 사전에 작동되는게 아니기 때문에 컴파일러가 해당 클래스를 미사용 클래스로 판단하고 삭제한다. 이를 방지하기 위해 백그라운드 핸들러 메서드에 @pragma('vm:entry-point') 코드를 적용해서 런타임에 실행하는 메서드임을 컴파일러에게 확실히 알려서 해당 부분을 최적화하지 않게 해야한다.

</aside>

참고사항

Cloud Messaging | FlutterFire

Notifications overview  |  Android Developers

Create and manage notification channels  |  Android Developers

import 'dart:async';

import 'package:bosanjin_protector_m2s/firebase_options.dart';
import 'package:bosanjin_protector_m2s/retrofit/service/login_service.dart';
import 'package:dio/dio.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:shared_preferences/shared_preferences.dart';

class FirebaseUtils {
  FirebaseUtils._();

  static bool _isFlutterLocalNotificationsInitialized = false;

  static late final String fcmToken;

  static late final AndroidNotificationChannel channel;
  static late final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;

  @pragma('vm:entry-point')
  static Future<void> firebaseMessagingBackgroundHandler(
    final RemoteMessage message,
  ) async {
    await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
    await setUpFlutterNotifications();
    showFlutterNotification(message);
  }

  static Future<void> setUpFlutterNotifications() async {
    if (_isFlutterLocalNotificationsInitialized) {
      return;
    }

    final fcmInstance = FirebaseMessaging.instance;

    channel = const AndroidNotificationChannel(
      'high_importance_channel',
      '알람',
      description: '응급상황 발생 시 전송을 위한 알람 채널입니다.',
      importance: Importance.max,
    );

    flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

    // 아이폰용 설정
    // await fcmInstance.setForegroundNotificationPresentationOptions(
    //   alert: true,
    //   badge: true,
    //   sound: false,
    // );

    // 플러터파이어 홈페이지 예시 코드지만 해당 코드로 구현할 경우 flutterLocalNotificationsPlugin이 초기화되지 않았다는 오류가 발생한다.
    // await flutterLocalNotificationsPlugin
    //     .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
    //     ?.createNotificationChannel(channel);

    await flutterLocalNotificationsPlugin.initialize(
      InitializationSettings(
        android: AndroidInitializationSettings(
          '@mipmap/ic_launcher',
        ),
      ),
    );

    fcmInstance.onTokenRefresh.listen(
      (final String event) {
        sendFcmToken(event);

        _setPref(event);
      },
    );

    fcmToken = await fcmInstance.getToken() ?? '';

    // fcmInstance.getInitialMessage().then((final RemoteMessage? value) {
    //   final a = value;
    // });

    _isFlutterLocalNotificationsInitialized = true;
  }

  static void showFlutterNotification(final RemoteMessage message) {
    final data = message.data;

    // final android = message.notification?.android;
    // if (data != null && android != null) {
    if (data.isNotEmpty) {
      flutterLocalNotificationsPlugin.show(
        data.hashCode,
        data['title'],
        data['body'],
        NotificationDetails(
          android: AndroidNotificationDetails(
            channel.id, channel.name, channelDescription: channel.description, importance: Importance.max,
            // icon: Assets.imagesSplashIcon2,
          ),
        ),
      );
    }
  }

  static Future<void> _setPref(final String fcmToken) async {
    final pref = await SharedPreferences.getInstance();
    unawaited(pref.setString('fcmToken', fcmToken));
  }

  static Future<void> sendFcmToken(final String fcmToken) async {
    final login_service = await Login_Service(
      Dio(),
    ).fcm_token_send(fcmToken);
  }
}
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  await FirebaseUtils.setUpFlutterNotifications();
  FirebaseMessaging.onMessage.listen(FirebaseUtils.showFlutterNotification);
  FirebaseMessaging.onBackgroundMessage(FirebaseUtils.firebaseMessagingBackgroundHandler);

  runApp(const MyApp());
}

웹에서 FCM 적용하려면 참고

FlutterFire Push Notifications via FCM — Flutter Web

config 관련 정보는 파이어베이스 프로젝트 설정 - 일반 - 웹 앱 선택하면 나온다.

프로젝트 설정 - 클라우드 메시징에 들어가서 웹 앱 구성에서 키를 생성해야 한다.

Untitled