Flutter local notification (feat.firebase FCM)

강정우·2023년 10월 24일
0

Flutter&Dart

목록 보기
72/87
post-thumbnail
  • 이전 포스팅에서는 local-notification을 사용하기 위한 설정을 잡았다. 이제 프로젝트에서 사용하기위한 설정과 실제 알림 코드를 작성해보자.

프로젝트 설정코드 (notification 초기화 코드)

  • 이때 notification 초기화는 보통 flutter create 했을 때 기준 MyHomePage의 inistState() 메서드에서 진행한다.
    그리고 이때 앞서도 말했는데 이 initState() 메서드는 async는 동작하지 않으므로 각각의 메서드들을 명시할 때 async를 걸어주는 것이 좋다.

설정

Foground / Backgroud

 Future<void> _initLocalNotification() async {
   FlutterLocalNotificationsPlugin _localNotification = FlutterLocalNotificationsPlugin();
   AndroidInitializationSettings initSettingsAndroid = const AndroidInitializationSettings('favicon');
   DarwinInitializationSettings initSettingsIOS = const DarwinInitializationSettings(
                                                           requestSoundPermission: false,
                                                           requestBadgePermission: false,
                                                           requestAlertPermission: false,
                                                         );
   InitializationSettings initSettings = InitializationSettings(android: initSettingsAndroid, iOS: initSettingsIOS);
   await _localNotification.initialize(
     initSettings,
     onSelectedNotification:(String? payload){
     	// '여기에 알람 클릭 시 실행할 라우팅이라든지, 로직 추가 예를 들어'
     	final _controller = Get.put(RoutePageController());
     	_controller.tabIndex.value=1
     	Get.toNamed('/routePage);
   	 }
   );
 }
  • initialize()에서 onSelectedNotification 속성값은 (String? payload) 문자열을 리턴 하며,
    해당 문자열 안에는 푸시를 전송할 때 설정하는 payload 값을 가지고 있어, 해당 payload 안에 넣어놓은 딥링크를 파싱해서 라우팅에 사용하면 된다.

  • 참고로 저기 DarwinInitializationSettings 에서 Permission을 true로 주면 앱 실행하자마자 요청 권한을 묻는다. 그래서 통상 true로 설정한다.

  • 이미지는 앞선 포스팅에 적혀있는데 drawable에 아이콘을 넣었다면 따로 경로, 확장자 없이 그냥 파일 이름만 명시해주면 된다.

Terminate

Future<void> _listenerWithTerminated() async {
    FlutterLocalNotificationsPlugin _localNotification = FlutterLocalNotificationsPlugin();
    NotificationAppLaunchDetails? details = await _localNotification.getNotificationAppLaunchDetails();
    if (details != null) {
      if (details.didNotificationLaunchApp) {
        if (details.payload != null) {
          _localNotificationRouter(details.payload!);
        }
      }
    }
  }
  • 앱 실행시 푸시를 클릭해서 들어오게 되면 NotificationAppLaunchDetails 객체에 payload 값이 들어가 있는데,
    이 부분을 활용해서 사용하게 되면 앱 종료 상태에서도 푸시를 열 수 있다.

  • NotificationAppLaunchDetails 객체에 payload 값은 한 번 수신 후에 사라지지 않기에 초기 함수 한 번만 실행해야 한다.

프로젝트 사용코드

사용

  • android에서는 channel Id / channel Name 설정이 필수 값으로 해당 채널 이름이 시스템 설정의 앱 알림 카테고리로 등록된다
    ios는 앞서 권한 요청을 받은 부분의 사용 여부만 넣어주면 된다
final notifications = FlutterLocalNotificationsPlugin();
AndroidNotificationChannel channel = const AndroidNotificationChannel(
    'high_importance_channel',
    'High Importance Notifications',
    description:
    'This channel is used for important notifications.',
  );

showNotification() async {
  const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
    '유니크한 알림 채널 ID',
    '채널 이름',
    channelDescripttion:'알림종류 설명',
    priority: Priority.high,
    importance: Importance.max,
    color: Color.fromARGB(255, 255, 0, 0),
    showWhen:false
  );

  const iosDetails = DarwinNotificationDetails(
    presentAlert: true,
    presentBadge: true,
    presentSound: true,
    badgeNumber: 1
  );
  
  const NotificationDetails platformChannelSpecifics = NotificationDetails(
    android: adnroidDetails,
    iOS: iosDetails
  );

  // 알림 id, 제목, 내용 맘대로 채우기
  notifications.show(
      1,
      '제목1',
      '내용1',
      NotificationDetails(android: androidDetails, iOS: iosDetails)
  );
}
  • 참고로 이때 채널을 명시해주었다면 AndroidManifest에서 <meta-data> 에 명시해줘야한다.
  • 이렇게 설정을 해주었다면 이제 .show() 메서드로 실제 사용자 눈에 표출할 수 있다.
 Future<void> showPushAlarm() async {
    FlutterLocalNotificationsPlugin _localNotification = FlutterLocalNotificationsPlugin();
    await _localNotification.show(
      0, 
      '로컬 푸시 알림', 
      '로컬 푸시 알림 테스트',
      NotificationDetails(android: androidDetails, iOS: iosDetails),
      payload: 'deepLink');
 }
  • 요청 권한 함수 이 요청 권한 함수는 <MyApp>에서 build 메서드 바로 위에서 실행해주면 된다.
void reqeustPermission(){
  flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermission(alert:true, badge:true, sound:true);
}

추가 설정

예약 알람

  • 특정 시간대 전송이 필요할 떄 타임존을 사용하여 날짜 또는 시간대 설정이 가능하다
    여기서 설정할 때 Dration을 사용하여 매시/매일/주/월간 전송을 커스텀 할 수 있다
 tz.TZDateTime _timeZoneSetting({
    required int hour,
    required int minute,
  }) {
    tz.initializeTimeZones();
    tz.setLocalLocation(tz.getLocation('Asia/Seoul'));
    tz.TZDateTime _now = tz.TZDateTime.now(tz.local);
    tz.TZDateTime scheduledDate =
        tz.TZDateTime(tz.local, _now.year, _now.month, _now.day, hour, minute);

    return scheduledDate;
  }

특정 날짜 전송

  • zonedSchedule() 함수 기능으로 로컬 푸시를 예약할 수 있다
    여기서 설정되는 timeZone은 앞서 설명한 타임존으로 넣어서 사용하면 된다
Future<void> selectedDatePushAlarm() async {
    FlutterLocalNotificationsPlugin _localNotification =
        FlutterLocalNotificationsPlugin();

  await _localNotification.zonedSchedule(
      1,
      '로컬 푸시 알림 2',
      '특정 날짜 / 시간대 전송 알림',
      _timeZoneSetting(),
      _details,
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.absoluteTime,
      androidAllowWhileIdle: true,
    );
  }

매일 전송

  • 옵션을 추가해주면 타임존에 세팅된 시간대로 매일 같은 시간에 로컬 푸시를 전송한다
matchDateTimeComponents: DateTimeComponents.time,

주/월간 전송

  • 주/월간 전송도 일 전송 방식과 같다
matchDateTimeComponents: DateTimeComponents.dayOfWeekAndTime,
matchDateTimeComponents: DateTimeComponents.dayOfMonthAndTime,

전송 취소

  • 등록된 스케쥴 알림의 id로 구독 취소
FlutterLocalNotificationsPlugin _localNotification = FlutterLocalNotificationsPlugin();
await _localNotification.cancel(1);
  • 등록된 모든 스케쥴 알림 한 번에 취소
FlutterLocalNotificationsPlugin _localNotification = FlutterLocalNotificationsPlugin();
_localNotification.cancelAll();
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글