⭐️ 개발/플러터

[패캠] - flutter_local_notifications (1) 단순 알람 추가

짱구러버 2022. 11. 17. 01:42
728x90

들어가기 앞서...

외부 패키지를 사용해서 앱내 알림을 띄우는 방법을 알아볼 것이다.

앱내 알림 하는 방법은 크개 두가지가 있다.

 

1. Cloud push message

관리자가 다수의 인원한테 메세지를 보낼때 클라우드를 통해서 보내는 것

2. Local alarm message

앱 자체에서 발송 시간, 발송 메세지를 알고 있고, 자체적으로 메세지를 보내는것

3. 차이점

클라우드 측에서 관리자가 발송한 메세지냐 ? vs 앱 자체에서 보냈고, 시간 및 내용을 알 수 있는 메세지냐 ?

 

왼) Cloud push message, 오) Local alarm message

출처 : https://pub.dev/packages/flutter_local_notifications

 

flutter_local_notifications | Flutter Package

A cross platform plugin for displaying and scheduling local notifications for Flutter applications with the ability to customise for each platform.

pub.dev


본문으로...

1.  패키지를 훓어보자!

1) 지원 되는 플랫폼!

2) 기능!

출처: https://pub.dev/packages/flutter_local_notifications#-features

  • 기본 알림 표시 (Display basic notifications)
  • 알림이 표시되어야 하는 시간 예약
  • 주기적으로 알림 표시 (간격 기반) 
  • 매일 지정된 시간에 알림이 표시되도록 예약
  • 매주 지정된 날짜와 시간에 알림이 표시되도록 예약
  • 나중에 표시되도록 예약된 보류 중인 알림 요청 목록을 검색
  • ID 또는 모든 ID 별 알림 취소/ 제거
  • 사용자 지정 알림 소리 지정
  • 사용자가 알림을 탭했을때, 앱이 포그라운드, 백그라운드, 종료되었을떄 처리하는 기능
  • 알림을 탭하여 앱이 실행되었는지 확인

[알림 단순표시!]

1. 패키지 설치

새롭운 패키지 설치 방법!

가장 마지막 버전을 다운로드 해준다!

2. [Android] Native 세팅

3.0.1+4 부터는 필요 설정 양이 줄어 들었다!

이전 버전은 READEME.md 를 참고 해주면 된다!

 

2-1. android > app > src > main > AndroidMainifext.xml 

기기가 잠겨있을떄도 출력하기 위한 설정

<activity
...
	android:showhenLocked="true"
	android:turnScreenOn="true"    
>

2-2. [IOS] native 세팅

Ios 는 기본적으로 어플이 열려있을때(foreground) 알람이 울리지 않도록 설정되어있다.

Ios 10 이상 에서 프레젠테이션 옵션을 사용해 foreground 에 있는 동안 알림이 표시되도록 구성한다!

if #available(iOS 10.0, *) {
  UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}

3. [main.dart] initialisation 세팅

초기화 작업

초기화는 한번만 수행을 해야하기 떄문이다.

void main() {
  // 플러터 엔진과 상호작용을 위해서 선언
  WidgetsFlutterBinding.ensureInitialized();
  _initNotiSetting();
  runApp(const MyApp());
}
// flutter_local_notifications 패키지 안에 FlutterLocalNotificationsPlugin의 생성자가 필요하기 때문에,import 해주자!
// 그리고 외부에서 이 생성자를 접근 할 일이 있으니, _initNotiSetting() 안에 넣지 않았다.

final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

// private 으로 작성된 이유는 이 파일 내부에서만 접근할 것이기 때문
void _initNotiSetting() async {
  const initializationSettingsAndroid =
      AndroidInitializationSettings('@mipmap/ic_launcher');

  // 메개변수를 보면 알듯이 6개의 매개변수가 defaultValue 가 true 이다. 변경하려면 이렇게 작성
  // 앱이 처음 구동 되면 Permission 을 체크하는데, 지금은 앱이 추가된 시점에 물어보겠다라는 의미로 false
  const initializationSettingsIOS = DarwinInitializationSettings(
    // 이 포그라운드에 있는 동안 알림이 트리거되면 경고를 나타내는 기본 설정이 표시
    requestAlertPermission: true,
    // 앱이 포그라운드에 있는 동안 알림이 트리거될 때 배지 값을 적용해야 하는지 여부
    requestBadgePermission: true,
    // 앱이 포그라운드에 있을 때 알림이 트리거될 때 소리를 재생해야 하는지 여부
    requestSoundPermission: true,
  );

  // ios, android 초기화 하는 함수들을 변수에 저장해두고  InitializationSettings 생성자에 보낸다.
  const initializationSettings = InitializationSettings(
    android: initializationSettingsAndroid,
    iOS: initializationSettingsIOS,
  );

  final result = await flutterLocalNotificationsPlugin.initialize(
    initializationSettings,
  );

  print(result);
}

print(result);

 

 

4. 알림 추가하기!

4-1. UI 만들기 

body: (
	ElevatedButton(
    	onPressed: () {},
        child: const Text('알림 버튼'),
    );
)

4-2. onPressed 함수 추가

// FlutterLocalNotificationsPlugin 객체를 불러와야하는데, 이미 main.dart 에 선언해주었으니 가져오면 된다.
final notification = FlutterLocalNotificationsPlugin();

ElevatedButton(
    onPressed: () async {
      // flutterLocalNotificationsPlugin 객체를 불러온다.
      final notification = flutterLocalNotificationsPlugin;
      // android AndroidNotificationDetails 객체 생성
      const android = AndroidNotificationDetails(
        '0',
        'android 알림 제목',
        channelDescription: 'android 알림 바디',
        importance: Importance.max,
        priority: Priority.max,
      );
      // ios DarwinNotificationDetails 객체 생성
      const ios = DarwinNotificationDetails();

      const detail = NotificationDetails(
        android: android,
        iOS: ios,
      );

      // 비동기로 작성한 이유는, requestPErmissions 의 결과값이 중요하기 때문
      // 안드로이드일때는 무조건 true 이고, ios 일때는 requestPermission 결과를 가져와야함
      // requestPermissions 가 nullable 한값이기 때문에 만약에 null 로 오면 false 로 값받는다.
      final permission = Platform.isAndroid
          ? true
          : await notification
                  .resolvePlatformSpecificImplementation<
                      IOSFlutterLocalNotificationsPlugin>()
                  ?.requestPermissions(
                      alert: true, badge: true, sound: true) ??
              false;
      if (!permission) {
        // 만약 permission 이 false 라면 알람을 띄워줄 수 없으니, 조건문 작성
        // await showNotiPermissionDialog(context);
        // return toast 권한이 없습니다.
        return;
      }
      await flutterLocalNotificationsPlugin.show(
          0, 'ios 알림 제목', 'ios 알림 내용', detail);
    },
    child: const Text('알림 버튼')),
const Center(
  child: Text('hi'),
)

 

추가로 주의 해야하는점! 

id 값은 unique 해야한다.

단순 알림 호출 코드 

await flutterLocalNotificationsPlugin.show(
    0, // int 고유 id값
    'plain title', // String? title 제목
    'plain body', // String? body 내용
    detail, // NotificationDetails? notificationDetails 의 객체 값
  );

 

 

5. 알림 스케쥴링!

매일 지정 된 시간에 알림이 표시되도록 예약

UTC 시간 기준으로 되어있고, TZDateTime 을 사용해야한다. 

출처:  https://pub.dev/packages/timezone

 

 

timezone | Dart Package

Time zone database and time zone aware DateTime.

pub.dev

출처: https://pub.dev/packages/flutter_native_timezone

 

flutter_native_timezone | Flutter Package

A flutter plugin for getting the local timezone of the os.

pub.dev

5-1. timezone 패키지 다운 

 

import 

import 'package:timezone/data/latest.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

   초기화 작업

tz.initializeTimeZones();

// 'Asia/Seoul'
final String? timeZoneName = await FlutterNativeTimezone.getLocalTimezone(); 

tz.setLocalLocation(tz.getLocation(timeZoneName!));
// 타임존 셋팅 필요
final now = tz.TZDateTime.now(tz.local);
var notiDay = now.day;

// 예외처리
if (now.hour > hour || now.hour == hour && now.minute >= minute) {
  notiDay = notiDay + 1;
}

 

매일 지정된 시간에 알림이 표시되도록 예약

await notification.zonedSchedule(
  1,
  alarmTitle,
  alarmDescription,
  tz.TZDateTime(
    tz.local,
    now.year,
    now.month,
    notiDay,
    hour,
    minute,
  ),
  detail,
  androidAllowWhileIdle: true,
  uiLocalNotificationDateInterpretation:
      UILocalNotificationDateInterpretation.absoluteTime,
  matchDateTimeComponents: DateTimeComponents.time,
  payload: DateFormat('HH:mm').format(alarmTime),
);

 

6. 알림 삭제!

unique 한 id 값 그대로 .cancle(id) 호출시 알람이 삭제 된다.

await FlutterLocalNotificationsPlugin().cancel(id)

끝으로...

  1. flutter local_notifincation 패키지 사용으로 알림 단순 호출이 가능하다!
  2. flutter_native_timezone 패키지 사용으로 알림 스케쥴링이 가능하다!

 

728x90