민프

[Flutter] FCM 설정 코드 본문

[Flutter]

[Flutter] FCM 설정 코드

민프야 2024. 9. 10. 11:16

자세한 코드는 아래를 참고해주세요

https://pub.dev/packages/firebase_messaging/example

 

firebase_messaging example | Flutter package

Flutter plugin for Firebase Cloud Messaging, a cross-platform messaging solution that lets you reliably deliver messages on Android and iOS.

pub.dev

pubspec.yaml


  # FCM
  firebase_messaging: ^15.1.0
  # 포그라운드에서도 알림 나올 수 있게 해주는 패키지
  flutter_local_notifications: ^17.2.2
  # 퍼미션 핸들러
  permission_handler: ^11.3.1
android/app/AndroidManifest.xml


<manifest xmlns:android="http://schemas.android.com/apk/res/android">
	.
    .
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
main.dart


Future<void> main() async {
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  runApp(const MyApp());
}
.
.
.

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print("Handling a background message: ${message.messageId}");
}

 

main or splash




// FCM 알림 설정을 초기화하는 함수
Future<void> setupFlutterNotifications() async {
  // 알림이 이미 초기화된 경우, 함수 종료
  if (isFlutterLocalNotificationsInitialized) {
    return;
  }

  // Android 13 이상에서 알림 권한을 요청
  if (await Permission.notification.isDenied) {
    await Permission.notification.request();
  }

  // 로컬 알림 플러그인 초기화
  localNotification = FlutterLocalNotificationsPlugin();
  var initializationSettingsAndroid = const AndroidInitializationSettings('@mipmap/ic_launcher'); // Android 초기화 설정
  var initializationSettingsIOS = DarwinInitializationSettings(
    requestAlertPermission: true, // iOS에서 알림 권한 요청
    requestBadgePermission: true, // iOS에서 배지 권한 요청
    requestSoundPermission: true, // iOS에서 소리 권한 요청
    onDidReceiveLocalNotification: (id, title, body, payload) async {
      // iOS 포그라운드 알림 수신 시 처리하는 로직
    },
  );

  // Android 및 iOS에 대한 초기화 설정을 종합
  var initializationSettings = InitializationSettings(
    android: initializationSettingsAndroid,
    iOS: initializationSettingsIOS,
  );

  // 로컬 알림 초기화
  localNotification.initialize(
    initializationSettings,
    onDidReceiveNotificationResponse: (NotificationResponse details) async {},
  );

  // 알림 채널 설정 (Android에서 알림을 구분하는 채널)
  channel = const AndroidNotificationChannel(
    'high_importance_channel', // 채널 ID
    'High Importance Notifications', // 채널 이름
    description: 'This channel is used for important notifications.', // 채널 설명
    importance: Importance.high, // 알림의 중요도를 설정 (high는 중요한 알림)
  );

  // Android 알림 채널 생성
  localNotification
      .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);

  // Firebase 메시지 수신 핸들러 (포그라운드 상태에서 메시지를 수신할 때 호출)
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    // 메시지에 포함된 알림 데이터를 가져옴
    RemoteNotification? notification = message.notification;
    AndroidNotification? android = message.notification?.android;

    // 알림 및 Android 알림이 유효할 경우
    if (notification != null && android != null) {
      // 로컬 알림을 보여줌
      localNotification.show(
        notification.hashCode,
        notification.title,
        notification.body,
        NotificationDetails(
          android: AndroidNotificationDetails(
            channel.id, // 채널 ID
            channel.name, // 채널 이름
            channelDescription: channel.description, // 채널 설명
            icon: android.smallIcon ?? '@mipmap/ic_launcher', // 기본 아이콘 설정
          ),
        ),
        payload: message.data['clickAction'].toString(), // 알림 클릭 시 동작을 위한 데이터
      );
    }
  });

  // 앱이 종료된 상태에서 알림을 통해 앱이 시작될 때 메시지를 처리
  FirebaseMessaging.instance.getInitialMessage().then((message) async {
    if (message != null) {
      // 필요한 데이터 처리
    }
  });

  // 사용자가 알림을 클릭하여 앱을 열었을 때 처리하는 핸들러
  FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
    debugPrint('Message clicked: ${message.notification?.title}');
    debugPrint('Message clicked: ${message.notification?.body}');
    debugPrint('Message clicked: ${message.data}');
  });

  // 알림 초기화 완료 플래그를 true로 설정
  isFlutterLocalNotificationsInitialized = true;
}


// FCM 메시지를 로컬 알림으로 표시하는 함수
void showFlutterNotification(RemoteMessage message) {
  RemoteNotification? notification = message.notification; // 메시지에서 알림 데이터를 추출
  AndroidNotification? android = message.notification?.android; // 메시지에서 Android 알림 데이터를 추출
  if (notification != null && android != null) {
    localNotification.show(
      notification.hashCode,
      notification.title,
      notification.body,
      NotificationDetails(
        android: AndroidNotificationDetails(
          channel.id, // 채널 ID
          channel.name, // 채널 이름
          channelDescription: channel.description, // 채널 설명
          icon: 'launch_background', // 기본 아이콘 설정
        ),
      ),
    );
  }
}

  // Firebase와 FCM 초기화 함수
  Future<void> _initializeFirebaseAndFCM() async {
    await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); // Firebase 초기화

    // Firebase Analytics 초기화
    analytics = FirebaseAnalytics.instance;

    // 백그라운드 메시지 핸들러 등록
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
    // FCM 알림 설정 초기화
    await setupFlutterNotifications();

    // FCM 토큰을 가져와서 출력
    FirebaseMessaging.instance.getToken().then((token) {
      print('FCM Token: $token');
    });

    // 포그라운드 상태에서 FCM 메시지 수신 시 알림 표시
    FirebaseMessaging.onMessage.listen(showFlutterNotification);

    // 사용자가 알림을 클릭하여 앱이 열렸을 때 처리
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      print('A new onMessageOpenedApp event was published!');
    });
  }
Comments