728x90
학습목표
1. Firebase cloud messaging & foreground notification 기능 구현
앱이 실행 중일 때 notification 받도록 구현
2. Firebase cloud messaging & background notification 기능 구현
앱이 종료되었을 때 notification 받도록 구현
3. 특정 시간에 알람 설정 시, 앱이 실행되고 소리 또는 진동이 울리는 기능 구현
진동 모드, 무음 모드일 때 어떻게 처리하는지 찾아보기
회고
1. Firebase cloud messaging & foreground notification 기능 구현
앱이 실행 중일 때 notification 받도록 구현
2. Firebase cloud messaging & background notification 기능 구현
앱이 종료되었을 때 notification 받도록 구현
import 'dart:async';
import 'dart:math';
import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:notify/layout/default_layout.dart';
import 'package:notify/main.dart';
import 'package:notify/utils/notification_util.dart';
Future<void> onBackgroundMessage(RemoteMessage message) async {
// 기존
// await Firebase.initializeApp();
// 앱 실행 코드 추가
await init();
runApp(const App());
print('background messgae !!!');
print(message.messageId);
if (message.data.containsKey('data')) {
// Handle data message
final data = message.data['data'];
print(data);
}
if (message.data.containsKey('notification')) {
// Handle notification message
final notification = message.data['notification'];
print(notification);
}
// Or do other work.
// awesome_notification background handler
await AwesomeNotifications().createNotification(
content: NotificationContent(
id: 1,
channelKey: 'basic_channel',
title: message.notification!.title!,
body: message.notification!.body!,
));
}
class FCM {
final _firebaseMessaging = FirebaseMessaging.instance;
final streamCtlr = StreamController<String>.broadcast();
final titleCtlr = StreamController<String>.broadcast();
final bodyCtlr = StreamController<String>.broadcast();
setNotifications() {
FirebaseMessaging.onBackgroundMessage(onBackgroundMessage);
// handle when app in active state
forgroundNotification();
// handle when app running in background state
backgroundNotification();
// handle when app completely closed by the user
terminateNotification();
// With this token you can test it easily on your phone
final token =
_firebaseMessaging.getToken().then((value) => print('Token: $value'));
}
forgroundNotification() {
FirebaseMessaging.onMessage.listen(
(message) async {
print('foregroundmessage');
print(message);
if (message.data.containsKey('data')) {
// Handle data message
streamCtlr.sink.add(message.data['data']);
}
if (message.data.containsKey('notification')) {
// Handle notification message
streamCtlr.sink.add(message.data['notification']);
}
// Or do other work.
titleCtlr.sink.add(message.notification!.title!);
bodyCtlr.sink.add(message.notification!.body!);
// awesome_notifications
// await AwesomeNotifications().createNotification(
// content: NotificationContent(
// id: 1,
// channelKey: 'basic_channel',
// title: message.notification!.title!,
// body: message.notification!.body!));
},
);
}
backgroundNotification() {
FirebaseMessaging.onMessageOpenedApp.listen(
(message) async {
print('backgroundmessage');
print(message);
if (message.data.containsKey('data')) {
// Handle data message
streamCtlr.sink.add(message.data['data']);
}
if (message.data.containsKey('notification')) {
// Handle notification message
streamCtlr.sink.add(message.data['notification']);
}
// Or do other work.
titleCtlr.sink.add(message.notification!.title!);
bodyCtlr.sink.add(message.notification!.body!);
},
);
}
terminateNotification() async {
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
print('terminatemessage');
print(initialMessage);
if (initialMessage != null) {
if (initialMessage.data.containsKey('data')) {
// Handle data message
streamCtlr.sink.add(initialMessage.data['data']);
}
if (initialMessage.data.containsKey('notification')) {
// Handle notification message
streamCtlr.sink.add(initialMessage.data['notification']);
}
// Or do other work.
titleCtlr.sink.add(initialMessage.notification!.title!);
bodyCtlr.sink.add(initialMessage.notification!.body!);
}
}
dispose() {
streamCtlr.close();
bodyCtlr.close();
titleCtlr.close();
}
}
알람 소리 재생 페이지
// import 'package:firebase_database/firebase_database.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:notify/addalarm/add_alarm.dart';
import 'package:notify/alarmlog/alarm_log.dart';
import 'package:notify/alarmsettings/alarm_settings.dart';
import 'package:notify/layout/default_layout.dart';
import 'package:notify/routinealarm/routine_alarm.dart';
import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:notify/constraints.dart';
import 'package:notify/myalarm/my_alarm.dart';
import 'package:notify/sharealarm/share_alarm.dart';
import 'package:get/get.dart';
class AlarmSoundPage extends StatefulWidget {
final AudioPlayer player;
const AlarmSoundPage({
Key? key,
required AudioPlayer this.player,
}) : super(key: key);
@override
_AlarmSoundPageState createState() => _AlarmSoundPageState();
}
class _AlarmSoundPageState extends State<AlarmSoundPage> {
int currentIndex = 0;
void changeCurrentIndex(int selectedIndex) {
setState(() {
currentIndex = selectedIndex;
});
}
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Scaffold(
backgroundColor: kBackgroundColor,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: height * 0.1,
),
Text(
'1월 11일 화요일',
style: TextStyle(
color: ktextColor,
),
),
SizedBox(
height: height * 0.05,
),
Text(
'3:55',
style: TextStyle(
color: ktextColor,
fontSize: 30,
),
),
Spacer(),
Row(
children: [
Expanded(
child: MaterialButton(
height: 50,
clipBehavior: Clip.antiAlias, // Add This
elevation: 0,
textColor: ktextColor,
color: kRedColor,
onPressed: () {
// _dateTime 시간에 알람 울리도록 추가
widget.player.stop();
Get.off(DefaultLayout());
},
child: const Text(
'종료하기',
style: TextStyle(fontSize: 16),
),
),
),
],
),
],
),
),
),
);
}
}
3. 특정 시간에 알람 설정 시, 앱이 실행되고 소리 또는 진동이 울리는 기능 구현
진동 모드, 무음 모드일 때 어떻게 처리하는지 찾아보기
return SafeArea(
child: Scaffold(
body: ListView(
padding: EdgeInsets.symmetric(horizontal: 15, vertical: 8),
children: <Widget>[
/* ******************************************************************** */
/* notification test */
TextDivisor(title: 'FCM Foreground\n알림 제목/텍스트'),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 20,
),
Text(
'Foreground 알림 제목:- $notificationTitle',
style: Theme.of(context).textTheme.headline6,
),
Text(
'Foreground 알림 텍스트:- $notificationBody',
style: Theme.of(context).textTheme.headline6,
),
// MaterialButton(
// onPressed: _showNotificationWithNoTitle,
// child: Text("noti"),
// ),
// 알람 추가
TextDivisor(title: '알람 추가하기'),
hourMinute12HCustomStyle(),
Container(
margin: EdgeInsets.symmetric(vertical: 100),
child: new Text(
_alarmTime.hour.toString().padLeft(2, '0') +
':' +
_alarmTime.minute.toString().padLeft(2, '0') +
':' +
_alarmTime.second.toString().padLeft(2, '0'),
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
Row(
children: [
Expanded(
child: MaterialButton(
height: 50,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(0)),
side: BorderSide(
color: Color(0xffdddddd),
),
),
clipBehavior: Clip.antiAlias, // Add This
elevation: 0,
textColor: Colors.white,
color: Colors.red,
onPressed: () {
// _dateTime 시간에 알람 울리도록 추가
Duration diff = _alarmTime.difference(DateTime.now());
int second = diff.inSeconds;
print("second : $second");
NotificationUtils.scheduleNotificationWithWakeUp(
27, (second));
},
child: const Text(
'추가하기',
style: TextStyle(fontSize: 16),
),
),
),
],
),
],
),
),
/* notification test */
static Future<void> scheduleNotificationWithWakeUp(
int id, int seconds) async {
Timer(
Duration(seconds: seconds),
// Ensure we have a unique alarm ID.
() async {
print('alarm excuted');
AudioCache cache = new AudioCache();
AudioPlayer player = new AudioPlayer();
String alarmAudioPath = "sounds/missyoulove.mp3";
player = await cache.loop(alarmAudioPath);
Get.to(AlarmSoundPage(player: player));
},
);
Get.to(const DefaultLayout());
}
추후에 FCM 개념을 적용하여 푸시로 처리하는 게 좋을 지 로컬에서 AndroidAlarmManager를 사용하는 게 좋을 지 고민해봐야겠다.
'독서' 카테고리의 다른 글
모각코(모더나 팀) 5회차 학습목표/회고 (1) | 2022.01.25 |
---|---|
모각코(모더나 팀) 4회차 학습목표/회고 (1) | 2022.01.18 |
모각코(모더나 팀) 2회차 학습목표/회고 (1) | 2022.01.04 |
모각코(모더나 팀) 1회차 학습목표/회고 (0) | 2021.12.28 |
자기관리론 (1) | 2021.12.04 |