고원빈

[frontend] 알람 설정 완료

1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:flutter/services.dart'; 2 import 'package:flutter/services.dart';
3 import '../../shared/colors.dart'; 3 import '../../shared/colors.dart';
4 +import 'package:rxdart/subjects.dart';
4 import 'package:flutter_screenutil/flutter_screenutil.dart'; 5 import 'package:flutter_screenutil/flutter_screenutil.dart';
6 +import 'package:flutter_local_notifications/flutter_local_notifications.dart';
7 +import 'package:flutter_application_1/src/screens/SettingPage.dart';
8 +import 'package:flutter/cupertino.dart';
9 +import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
10 +
11 +final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
12 + FlutterLocalNotificationsPlugin();
13 +// Streams are created so that app can respond to notification-related events since the plugin is initialised in the `main` function
14 +final BehaviorSubject<ReceivedNotification> didReceiveLocalNotificationSubject =
15 + BehaviorSubject<ReceivedNotification>();
16 +
17 +final BehaviorSubject<String> selectNotificationSubject =
18 + BehaviorSubject<String>();
19 +
20 +NotificationAppLaunchDetails notificationAppLaunchDetails;
21 +
22 +class ReceivedNotification {
23 + final int id;
24 + final String title;
25 + final String body;
26 + final String payload;
27 +
28 + ReceivedNotification({
29 + @required this.id,
30 + @required this.title,
31 + @required this.body,
32 + @required this.payload,
33 + });
34 +}
5 35
6 class Alarm extends StatefulWidget { 36 class Alarm extends StatefulWidget {
7 @override 37 @override
...@@ -9,16 +39,325 @@ class Alarm extends StatefulWidget { ...@@ -9,16 +39,325 @@ class Alarm extends StatefulWidget {
9 } 39 }
10 40
11 class _AlarmnState extends State<Alarm> { 41 class _AlarmnState extends State<Alarm> {
42 + FlutterLocalNotificationsPlugin fltrNotification;
43 +
44 + void initState() {
45 + super.initState();
46 +
47 + main();
48 + }
49 +
50 + Future<void> main() async {
51 + // needed if you intend to initialize in the `main` function
52 + WidgetsFlutterBinding.ensureInitialized();
53 + // NOTE: if you want to find out if the app was launched via notification then you could use the following call and then do something like
54 + // change the default route of the app
55 + // var notificationAppLaunchDetails =
56 + // await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
57 +
58 + var initializationSettingsAndroid =
59 + new AndroidInitializationSettings('app_icon');
60 + var initializationSettingsIOS = IOSInitializationSettings(
61 + requestAlertPermission: true,
62 + requestBadgePermission: true,
63 + requestSoundPermission: true,
64 + onDidReceiveLocalNotification:
65 + (int id, String title, String body, String payload) async {});
66 + var initializationSettings = InitializationSettings(
67 + initializationSettingsAndroid, initializationSettingsIOS);
68 + await flutterLocalNotificationsPlugin.initialize(initializationSettings,
69 + onSelectNotification: (String payload) async {
70 + if (payload != null) {
71 + debugPrint('notification payload: ' + payload);
72 + }
73 + });
74 + }
75 +
76 + void _requestIOSPermissions() {
77 + flutterLocalNotificationsPlugin
78 + .resolvePlatformSpecificImplementation<
79 + IOSFlutterLocalNotificationsPlugin>()
80 + ?.requestPermissions(
81 + alert: true,
82 + badge: true,
83 + sound: true,
84 + );
85 + }
86 +
87 + void _configureDidReceiveLocalNotificationSubject() {
88 + didReceiveLocalNotificationSubject.stream
89 + .listen((ReceivedNotification receivedNotification) async {
90 + await showDialog(
91 + context: context,
92 + builder: (BuildContext context) => CupertinoAlertDialog(
93 + title: receivedNotification.title != null
94 + ? Text(receivedNotification.title)
95 + : null,
96 + content: receivedNotification.body != null
97 + ? Text(receivedNotification.body)
98 + : null,
99 + actions: [
100 + CupertinoDialogAction(
101 + isDefaultAction: true,
102 + child: Text('Ok'),
103 + onPressed: () async {
104 + Navigator.of(context, rootNavigator: true).pop();
105 + await Navigator.push(
106 + context,
107 + MaterialPageRoute(
108 + builder: (context) =>
109 + SecondScreen(receivedNotification.payload),
110 + ),
111 + );
112 + },
113 + )
114 + ],
115 + ),
116 + );
117 + });
118 + }
119 +
120 + void _configureSelectNotificationSubject() {
121 + selectNotificationSubject.stream.listen((String payload) async {
122 + await Navigator.push(
123 + context,
124 + MaterialPageRoute(builder: (context) => SecondScreen(payload)),
125 + );
126 + });
127 + }
128 +
129 + @override
130 + void dispose() {
131 + didReceiveLocalNotificationSubject.close();
132 + selectNotificationSubject.close();
133 + super.dispose();
134 + }
135 +
12 Widget build(BuildContext context) { 136 Widget build(BuildContext context) {
13 final Size size = MediaQuery.of(context).size; 137 final Size size = MediaQuery.of(context).size;
14 return MaterialApp( 138 return MaterialApp(
15 title: 'Welcome to Flutter', 139 title: 'Welcome to Flutter',
16 home: Scaffold( 140 home: Scaffold(
17 appBar: AppBar( 141 appBar: AppBar(
18 - title: Text('Welcome to Flutter'), 142 + iconTheme: IconThemeData(color: Colors.black),
143 + backgroundColor: Colors.white,
144 + title: Text(
145 + 'Smart Medicine Box',
146 + style: TextStyle(
147 + color: Colors.black,
148 + fontSize: 20,
149 + fontFamily: 'Noto',
150 + fontWeight: FontWeight.bold),
151 + ),
152 + actions: [
153 + IconButton(
154 + icon: Icon(
155 + Icons.settings,
156 + color: Colors.black,
157 + ),
158 + onPressed: () {
159 + Navigator.push(
160 + context,
161 + MaterialPageRoute(
162 + builder: (BuildContext context) => SettingPage(),
163 + ));
164 + },
165 + )
166 + ],
167 + ),
168 + drawer: Drawer(
169 + child: ListView(
170 + children: [
171 + DrawerHeader(
172 + child: Text('Drawer Header'),
173 + decoration: BoxDecoration(
174 + color: Colors.blue,
175 + ),
176 + ),
177 + ListTile(
178 + title: Text('Test 1'),
179 + onTap: () {},
180 + ),
181 + ListTile(
182 + title: Text('Test 2'),
183 + onTap: () {},
184 + ),
185 + ListTile(
186 + title: Text('Test 3'),
187 + onTap: () {},
188 + ),
189 + ],
190 + ),
191 + ),
192 + body: FlatButton(
193 + height: size.height * 0.07,
194 + onPressed: () {
195 + _showDailyAtTime(1, 2);
196 + },
197 + child: Text(
198 + '알람 설정',
199 + textScaleFactor: 1.0,
200 + style: TextStyle(
201 + color: Colors.white,
202 + fontSize: 24,
203 + fontFamily: 'Noto',
204 + fontWeight: FontWeight.bold),
205 + ),
206 + color: Color(0xff8E97FD),
207 + shape:
208 + RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)),
209 + ),
210 + ),
211 + );
212 + }
213 +
214 + Future<void> _cancelNotification() async {
215 + await flutterLocalNotificationsPlugin.cancel(0);
216 + }
217 +
218 + Future<void> _showTimeoutNotification() async {
219 + var androidPlatformChannelSpecifics = AndroidNotificationDetails(
220 + 'silent channel id',
221 + 'silent channel name',
222 + 'silent channel description',
223 + timeoutAfter: 3000,
224 + styleInformation: DefaultStyleInformation(true, true));
225 + var iOSPlatformChannelSpecifics =
226 + IOSNotificationDetails(presentSound: false);
227 + var platformChannelSpecifics = NotificationDetails(
228 + androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
229 + await flutterLocalNotificationsPlugin.show(0, 'timeout notification',
230 + 'Times out after 3 seconds', platformChannelSpecifics);
231 + }
232 +
233 + Future<void> _cancelAllNotifications() async {
234 + await flutterLocalNotificationsPlugin.cancelAll();
235 + }
236 +
237 + /// 매일 지정된 시간에 Alarm 을 트는 Function
238 + Future<void> _showDailyAtTime(int a, int b) async {
239 + var time = Time(11, 24, 0);
240 + var androidPlatformChannelSpecifics = AndroidNotificationDetails(
241 + 'repeatDailyAtTime channel id',
242 + 'repeatDailyAtTime channel name',
243 + 'repeatDailyAtTime description');
244 + var iOSPlatformChannelSpecifics = IOSNotificationDetails();
245 + var platformChannelSpecifics = NotificationDetails(
246 + androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
247 + await flutterLocalNotificationsPlugin.showDailyAtTime(
248 + 1,
249 + '알람 시간 알림 ',
250 + '설정하신 시간인 ${_toTwoDigitString(time.hour)}${_toTwoDigitString(time.minute)}분입니다.',
251 + time,
252 + platformChannelSpecifics);
253 +
254 + var pendingNotificationRequests =
255 + await flutterLocalNotificationsPlugin.pendingNotificationRequests();
256 +
257 + print(pendingNotificationRequests.toList());
258 + }
259 +
260 + /// weekday 가 1부터 7순으로 일 월 화 수 목 금 토 일 순서로 구성이 되어 있음 이에 따라 설정한 Weekday time 에 학습 알람을 뛰어주는 역할을 해주는 함수
261 + Future<void> _showWeeklyAtDayAndTime(
262 + int a, int b, int weekday, int index, int idindex) async {
263 + print(index + idindex);
264 +
265 + Day setDay;
266 +
267 + if (weekday == 1) {
268 + setDay = Day.Monday;
269 + } else if (weekday == 2) {
270 + setDay = Day.Tuesday;
271 + } else if (weekday == 3) {
272 + setDay = Day.Wednesday;
273 + } else if (weekday == 4) {
274 + setDay = Day.Thursday;
275 + } else if (weekday == 5) {
276 + setDay = Day.Friday;
277 + } else if (weekday == 6) {
278 + setDay = Day.Saturday;
279 + } else if (weekday == 7) {
280 + setDay = Day.Sunday;
281 + }
282 +
283 + var time = Time(a, b, 0);
284 + var androidPlatformChannelSpecifics = AndroidNotificationDetails(
285 + 'show weekly channel id',
286 + 'show weekly channel name',
287 + 'show weekly description');
288 + var iOSPlatformChannelSpecifics = IOSNotificationDetails();
289 + var platformChannelSpecifics = NotificationDetails(
290 + androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
291 + await flutterLocalNotificationsPlugin.showWeeklyAtDayAndTime(
292 + index + idindex,
293 + '약통 알람 ',
294 + '알약 섭취 시간인 ${_toTwoDigitString(time.hour)}:${_toTwoDigitString(time.minute)}이 되었습니다.',
295 + setDay,
296 + time,
297 + platformChannelSpecifics);
298 + }
299 +
300 + String _toTwoDigitString(int value) {
301 + return value.toString().padLeft(2, '0');
302 + }
303 +
304 + Future<void> onDidReceiveLocalNotification(
305 + int id, String title, String body, String payload) async {
306 + // display a dialog with the notification details, tap ok to go to another page
307 + await showDialog(
308 + context: context,
309 + builder: (BuildContext context) => CupertinoAlertDialog(
310 + title: title != null ? Text(title) : null,
311 + content: body != null ? Text(body) : null,
312 + actions: [
313 + CupertinoDialogAction(
314 + isDefaultAction: true,
315 + child: Text('Ok'),
316 + onPressed: () async {
317 + Navigator.of(context, rootNavigator: true).pop();
318 + await Navigator.push(
319 + context,
320 + MaterialPageRoute(
321 + builder: (context) => SecondScreen(payload),
322 + ),
323 + );
324 + },
325 + )
326 + ],
327 + ),
328 + );
329 + }
330 +}
331 +
332 +class SecondScreen extends StatefulWidget {
333 + SecondScreen(this.payload);
334 +
335 + final String payload;
336 +
337 + @override
338 + State<StatefulWidget> createState() => SecondScreenState();
339 +}
340 +
341 +class SecondScreenState extends State<SecondScreen> {
342 + String _payload;
343 + @override
344 + void initState() {
345 + super.initState();
346 + _payload = widget.payload;
347 + }
348 +
349 + @override
350 + Widget build(BuildContext context) {
351 + return Scaffold(
352 + appBar: AppBar(
353 + title: Text('Second Screen with payload: ${(_payload ?? '')}'),
19 ), 354 ),
20 body: Center( 355 body: Center(
21 - child: Text('약병 내부 페이지 작업 영역'), 356 + child: RaisedButton(
357 + onPressed: () {
358 + Navigator.pop(context);
359 + },
360 + child: Text('Go back!'),
22 ), 361 ),
23 ), 362 ),
24 ); 363 );
......