Mobile Front/Flutter

[Flutter] 푸시 알림 보내기 (FCM push notification)

koh1018 2023. 3. 31. 20:27
반응형

 

저번 글에 이어 클라이언트 단에서의 푸시 알림 구현을 진행해보겠다.

구현할 코드를 크게 세 부분으로 나누면,

 

1. FCM 인증 및 초기 설정

2. 알림 구현

3. Firebase Token 발급

 

으로 나눌 수 있다.

 

 

먼저 구현에 앞서 패키지를 설치하겠다.

firebase_core: ^2.8.0
firebase_messaging: ^14.3.0
flutter_local_notifications: ^13.0.0

 

패키지 설치 및 프로젝트 - Firebase 연결은 어렵지 않아 생략하도록 하겠다.

 

 

fcmSetting.dart

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  await Firebase.initializeApp();

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

Future<String?> fcmSetting() async {
  // firebase core 기능 사용을 위한 필수 initializing
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  FirebaseMessaging messaging = FirebaseMessaging.instance;

  await messaging.setForegroundNotificationPresentationOptions(
    alert: true,
    badge: true,
    sound: true,
  );

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

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

  // foreground에서의 푸시 알림 표시를 위한 알림 중요도 설정 (안드로이드)
  const AndroidNotificationChannel channel = AndroidNotificationChannel(
      'somain_notification',
      'somain_notification',
      description: '소마인 알림입니다.',
      importance: Importance.max
  );

  // foreground 에서의 푸시 알림 표시를 위한 local notifications 설정
  final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel);

  // foreground 푸시 알림 핸들링
  FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    RemoteNotification? notification = message.notification;
    AndroidNotification? android = message.notification?.android;

    print('Got a message whilst in the foreground!');
    print('Message data: ${message.data}');

    if (message.notification != null && android != null) {
      flutterLocalNotificationsPlugin.show(
          notification.hashCode,
          notification?.title,
          notification?.body,
          NotificationDetails(
            android: AndroidNotificationDetails(
              channel.id,
              channel.name,
              channelDescription: channel.description,
              icon: android.smallIcon,
            ),
          ));

      print('Message also contained a notification: ${message.notification}');
    }
  });

  // firebase token 발급
  String? firebaseToken = await messaging.getToken();

  print("firebaseToken : ${firebaseToken}");

  return firebaseToken;
}

푸시 알림이 오는 상황은 Foreground, Background 두 가지로 구분할 수 있다.

간단하게 앱이 실행중일 때는 Foreground, 앱이 꺼져있거나 background로 실행중일 때 Background 상태이다.

 

위 두 상황에 대해 FCM은 각기 다른 핸들러를 사용한다. Background의 경우는 따로 핸들러를 구현해주지 않고 FCM initializing만 해줘도 된다.

하지만 Foreground의 경우 (앱이 기기 화면의 최상단에서 실행 중인 경우) 별도의 핸들러를 구현해야한다.

 

또 안드로이드의 경우 Foreground 상태에서 알림을 보내지 않도록 정책이 되어있기에 알림의 중요도를 따로 설정해줘야한다.

 

이를 위해서 외부 라이브러리인 flutter_local_notifications 를 사용한다. 이는 공식문서에서도 가이드해주고 있는 부분이다.

해당 라이브러리는 서버 없이 local 단에서 알림을 주는 패키지인데, 안드로이드에서 중요도를 설정해 Foreground 상태에서도 알림을 주게 할 수 있다.

 

위 코드에서 맨 아래쪽은 Firebase Token을 발급하여 리턴하는 코드이다.

이 토큰으로 알림을 보낼 유저를 특정해낼 수 있다.

 

 

위 코드는 main에서 runApp이 실행되기 전에 불러와야한다.

void main() async {
  WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();

  // notification 설정
  String? firebaseToken = await fcmSetting();

  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: WebViewScreen(
        firebaseToken: firebaseToken,
      ),
    ),
  );
}

필자는 위와 같이 firebaseToken을 받은 후, statefulwidget에 넘겨주었다.

그리고 해당 위젯에서 서버로 넘겨주는 로직을 구현하였다. (firebaseToken 등록용 별도의 백엔드 api 필요)

 

 

마지막으로 AndroidManifest.xml을 수정해준다.

<!--   알림 받기    -->
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver" android:exported="false" />
<!--   Notification    -->
<meta-data
   android:name="com.google.firebase.messaging.default_notification_channel_id"
   android:value="somain_notification" />

위 태그는 <application> 태그 안에 넣어주면 된다.

 

 

ios의 경우는 xcode를 설정해야한다. 아래 공식 문서를 참고하길 바란다.

 

FCM via APNs Integration | FlutterFire

iOS & macOS require additional configuration steps to be completed before you can receive messages.

firebase.flutter.dev

 

 

이제 토큰을 가지고 알림을 보내면 수신할 수 있다.

 

알림을 보내는 구체적인 백엔드 구현은 아래 링크에서 확인할 수 있다.

 

[SpringBoot] FCM을 통해 Push 알림 보내기 (FCM push notification)

FCM은 Firebase Cloud Messaging의 약자로 기존 GCM에서 모든 플랫폼에 푸쉬를 쉽게 보낼 수 있도록 통합된 솔루션이다. Notification 콘솔의 GUI나 Admin SDK를 이용해 서버 등에서 FCM의 백에 요청을 보내면, FCM

kbwplace.tistory.com

 

 

 

반응형