본문 바로가기
[Flutter]

Flutter Firebase Messaging (포그라운드 / 백그라운드 / 종료) 모두

by Hevton 2022. 12. 3.
반응형

 

삽질을 일주일 정도 하고 정리한 글입니다 ㅜ.ㅜ 도움이 되시면 좋겠습니다.

 

 

 

 

firebase configure가 이미 되어있는 전제 하에 설명하는 글이다!

이것이 안되어있다면 여기서 간단하고 빠르게 수행하고 이 글을 다시 보면 된다!

 

 

 

 

 

우선 pubspec.yaml 파일에 두가지 dependency를 추가한다.

  firebase_messaging: ^13.1.0
  flutter_local_notifications: ^12.0.4

firebase_messaging은 말그대로 fcm을 위한 것이고

flutter_local_notification은 특수 경우 처리를 위한 것이다.

 

FCM은 앱이 백그라운드 / 종료 상태에서 정상적으로 notification 알림 팝업이 동작한다.

하지만 앱이 포그라운드 상태일 경우에 notification 알림 팝업이 동작하지 않는다.

따라서 이를 띄워주기 위해서 flutter_local_notification을 이용한다.

 

 

 

 

Android -> app -> src -> main -> AndroidManifest

<Application> 태그 안에 아래 코드를 추가한다.

       <meta-data
           android:name="com.google.firebase.messaging.default_notification_channel_id"
           android:value="high_importance_channel"/>

 

 

 

 

flutter의 메인함수를 다음과 같이 구상한다.

const AndroidNotificationChannel channel = AndroidNotificationChannel(
  'high_importance_channel',
  'High Importance Notifications',
  description: 'This channel is used for important notifications.',
  importance: Importance.max,
);


FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

void main() async {

  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  FirebaseMessaging messaging = FirebaseMessaging.instance;

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  NotificationSettings settings = await messaging.requestPermission(
    alert: true,
    announcement: false,
    badge: true,
    carPlay: false,
    criticalAlert: false,
    provisional: false,
    sound: true,
  );

  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    alert: true, // Required to display a heads up notification
    badge: true,
    sound: true,
  );

  androidNotiSet();

  print('User granted permission: ${settings.authorizationStatus}');

  FirebaseMessaging.onMessage.listen((RemoteMessage message) async {

    const AndroidNotificationDetails androidNotificationDetails =
    AndroidNotificationDetails('high_importance_channel', 'High Importance Notifications',
        channelDescription: 'This channel is used for important notifications.',
        importance: Importance.max,
        priority: Priority.high,
        ticker: 'ticker');
    const NotificationDetails notificationDetails =
    NotificationDetails(android: androidNotificationDetails);
    await flutterLocalNotificationsPlugin.show(
        0, '${message.notification!.title}', '${message.notification!.body}', notificationDetails,
        payload: 'item x');

  });

  runApp(const MyApp());
}

 

여기서 나온 _firebaseMessagingBackgroundHandler 과, androidNotiSet 은 아래에 함수로 코드를 작성한다.

Future<void> androidNotiSet() async {


  if(Platform.isAndroid) {
    FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<
        AndroidFlutterLocalNotificationsPlugin>()!.requestPermission();


    await flutterLocalNotificationsPlugin
        .resolvePlatformSpecificImplementation<
        AndroidFlutterLocalNotificationsPlugin>()
        ?.createNotificationChannel(channel);
  }


  const AndroidInitializationSettings initializationSettingsAndroid =  AndroidInitializationSettings('app_icon');

  final DarwinInitializationSettings initializationSettingsIOS =  const DarwinInitializationSettings(
    requestAlertPermission: true,
    requestBadgePermission: true,
    requestSoundPermission: true,);

  final InitializationSettings initializationSettings = InitializationSettings(
    android: initializationSettingsAndroid,
    iOS: initializationSettingsIOS,);

  await flutterLocalNotificationsPlugin.initialize(initializationSettings);

}

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  print("Handling a background message: ${message.messageId}");
}

하나 세팅해야 할 것이 있다.

Android -> app -> src -> main -> res -> drawable 안에 app_icon.png의 임의의 아이콘을 추가해야 한다!

 

 

그리고 하나 자세히 설명하자면.. 위 코드 중에

FirebaseMessaging.onMessage.listen

이것은 포그라운드에서 FCM을 받았을 때 어떻게 처리할지에 대한 로직이다.

기본적으로 FCM은 백그라운드/Terminated에서 도착 시 FCM 메세지가 온 그대로 전달되어 팝업되는데

포그라운드에서 FCM을 받을 시 팝업되지 않는다. 따라서 Flutter_loca_notification을 이용해서 이 함수 안에서 커스텀으로 띄워야한다.

메세지 또한 커스텀 할 수 있고, FCM에서 온 데이터를 그대로 전달받아 사용할 수도 있다.

 

 

 

 

+ firebase_analytics는 FCM 필수 적용사항이 아니다.

+ FingerPrint는 적용하지 않아도 동작한다. FingerPrint는 Auth같은 로그인에서 필요.

+ 오류가 날 경우 pubspec.yaml에 다음을 추가한다

firebase_core_platform_interface: 4.5.1

 

참고

https://hevton.tistory.com/707

https://www.youtube.com/watch?v=2tjuUwNx6qk 

https://firebase.flutter.dev/docs/messaging/overview/

반응형