개발자
flutter_local_notifications를 사용해서 알림 기능을 구현하고 있는데, 함수는 작동하는데 알림이 안뜹니다. 권한도 설정했고 로컬 설정도 서울로 확인했는데, 시간 변환이 문제인 건지 온갖 걸 다해봐도 알림이 뜨지 않습니다. 며칠을 붙잡고 있는데 검토 한 번만 부탁드리겠습니다..
1import 'package:flutter/material.dart';
2import 'package:flutter_local_notifications/flutter_local_notifications.dart';
3import 'package:shared_preferences/shared_preferences.dart';
4import 'package:table_calendar/table_calendar.dart';
5import 'package:timezone/standalone.dart';
6import 'package:timezone/timezone.dart' as tz;
7import 'package:timezone/data/latest.dart' as tz;
8import 'main.dart';
9
10class ShuttleBus extends StatefulWidget {
11 const ShuttleBus({super.key});
12
13 @override
14 State<ShuttleBus> createState() => ShuttleBusState();
15}
16
17class ShuttleBusState extends State<ShuttleBus> {
18 CalendarFormat calendarFormat = CalendarFormat.month;
19 DateTime focusedDay = DateTime.now();
20 DateTime? selectedDay;
21 List<DateTime> markedDays = [];
22
23
24 //**초기 */
25 @override
26 void initState() {
27 super.initState();
28 tz.initializeTimeZones();
29 var seoul = tz.getLocation('Asia/Seoul');
30 tz.setLocalLocation(seoul);
31
32 AndroidInitializationSettings androidInitializationSettings = const AndroidInitializationSettings('mipmap/ic_launcher');
33 DarwinInitializationSettings iosInitializationSettings = const DarwinInitializationSettings(
34 requestAlertPermission: false,
35 requestBadgePermission: false,
36 requestSoundPermission: false,
37 );
38
39 InitializationSettings initializationSettings = InitializationSettings(
40 android: androidInitializationSettings,
41 iOS: iosInitializationSettings,
42 );
43
44 flutterLocalNotificationsPlugin.initialize(initializationSettings);
45 loadMarkedDays();
46 }
47
48
49 //**셔틀 예약 알림 */
50 Future<void> scheduleAlarm(DateTime scheduledNotificationDateTime) async {
51 var androidNotificationDetails = const AndroidNotificationDetails(
52 '1 channel id',
53 '2 channel name',
54 priority: Priority.high,
55 importance: Importance.max,
56 );
57
58 var notificationDetails = NotificationDetails(
59 android: androidNotificationDetails,
60 iOS: const DarwinNotificationDetails(badgeNumber: 1));
61
62 // 선택된 날짜에서 이틀 전의 오후 8시 30분 계산
63 var notificationTime = DateTime.now().add(const Duration(days: 2, hours: 22, minutes: 22));
64
65 // TZDateTime으로 변환
66 tz.TZDateTime scheduledTimeZoneDateTime =
67 tz.TZDateTime.from(notificationTime, tz.local);
68 print(tz.TZDateTime.now(tz.local));
69 print(notificationTime);
70 print(scheduledNotificationDateTime);
71
72 //푸시알림 내용
73 await flutterLocalNotificationsPlugin.zonedSchedule(
74 0, 'test title', 'test body', scheduledTimeZoneDateTime, notificationDetails,
75 androidScheduleMode: AndroidScheduleMode.inexactAllowWhileIdle,
76 uiLocalNotificationDateInterpretation:
77 UILocalNotificationDateInterpretation.absoluteTime);
78 print('scheduleAlarm completed');
79 }
80
81 //**알림 로드 및 로컬 저장 */
82 Future<void> loadMarkedDays() async {
83 SharedPreferences prefs = await SharedPreferences.getInstance();
84 setState(() {
85 markedDays = (prefs.getStringList('markedDays') ?? []).map((item) => DateTime.parse(item)).toList();
86 });
87 }
88
89 Future<void> saveMarkedDays() async {
90 SharedPreferences prefs = await SharedPreferences.getInstance();
91 await prefs.setStringList('markedDays', markedDays.map((item) => item.toString()).toList());
92 setState(() {});
93 }
94
95 //화면 위젯
96 @override
97 Widget build(BuildContext context) {
98 return Scaffold(
99 appBar: AppBar(
100 title: const Text('셔틀버스'),
101 ),
102 body: Padding(padding: const EdgeInsets.all(16),
103 child: ListView(
104 children: <Widget> [
105 const Text('운행시간',
106 style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
107 Padding(padding: const EdgeInsets.fromLTRB(10, 20, 10, 10),
108 child: Image.asset('assets/images/shuttle_bus_time.png')),
109 const SizedBox(height: 30),
110
111 const Text('셔틀 예약 알림',
112 style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
113
114 TableCalendar(
115 //locale: 'ko_KR',
116 firstDay: DateTime.now(),
117 lastDay: DateTime(2024, 6, 21),
118 focusedDay: focusedDay,
119 headerStyle: const HeaderStyle(formatButtonVisible: false),
120
121 eventLoader: (day) {
122 return markedDays.where((event) => isSameDay(event, day)).toList();
123 },
124 selectedDayPredicate: (day) {
125 return isSameDay(selectedDay, day);
126 },
127
128 onDaySelected: (selectedDay, focusedDay) async {
129 setState(() {
130 this.focusedDay = selectedDay;
131
132 if (markedDays.contains(selectedDay)) {
133 showDialog(
134 context: context,
135 builder: (context) => AlertDialog(
136 title: const Text("알림 삭제"),
137 content: const Text("셔틀 예약 알림을 삭제하시겠습니까?"),
138 actions: <Widget>[
139 TextButton(
140 child: const Text("예"),
141 onPressed: () {
142 markedDays.remove(selectedDay);
143 saveMarkedDays();
144 Navigator.of(context).pop();
145 },
146 ),
147 TextButton(
148 child: const Text("아니오"),
149 onPressed: (){
150 Navigator.of(context).pop();
151 },
152 ),
153 ],
154 ),
155 );
156 } else {
157 DateTime now = DateTime.now();
158 DateTime notificationTime = selectedDay.subtract(const Duration(days: 2)).add(const Duration(hours: 22, minutes: 20));
159 if (notificationTime.isBefore(now) || notificationTime.isAtSameMomentAs(now)) {
160 showDialog(
161 context: context,
162 builder: (context) => AlertDialog(
163 title: const Text("알림 불요"),
164 content: const Text("해당 날짜의 셔틀 신청 기간입니다.\n지금 바로 셔틀을 신청하세요."),
165 actions: <Widget>[
166 TextButton(
167 child: const Text("확인"),
168 onPressed: () {
169 Navigator.of(context).pop();
170 },
171 ),
172 ],
173 ),
174 );
175 } else {
176 showDialog(
177 context: context,
178 builder: (context) => AlertDialog(
179 title: const Text("알림 예약"),
180 content: const Text("알림을 예약하시겠습니까?"),
181 actions: <Widget>[
182 TextButton(
183 child: const Text("예"),
184 onPressed: () {
185 markedDays.add(selectedDay);
186 saveMarkedDays();
187 scheduleAlarm(selectedDay);
188 Navigator.of(context).pop();
189 },
190 ),
191 TextButton(
192 child: const Text("아니오"),
193 onPressed: () {
194 Navigator.of(context).pop();
195 },
196 ),
197 ],
198 ),
199 );
200 }
201 //this.focusedDay = selectedDay;
202 //this.selectedDay = selectedDay;
203 }
204 });
205 },
206 ),
207 const SizedBox(height: 30),
208
209 const Text('셔틀 예약',
210 style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
211 ]
212 )
213 )
214 );
215 }
216}
지금 가입하면 모든 질문의 답변을 볼 수 있어요!