Skip to content

Commit

Permalink
#9-アラーム起動時の処理
Browse files Browse the repository at this point in the history
日時指定アラーム予約、スヌーズ
現在の予約状況を見れるように
またこれらの確認用にalarm_viewにボタン追加
  • Loading branch information
MrMocchy committed Jun 17, 2022
1 parent 54921df commit b22e700
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 63 deletions.
136 changes: 125 additions & 11 deletions lib/model/ringing_alarm_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,45 @@ class RingingAlarm {
}

//予約済みの通知のリストを取得
List<PendingNotificationRequest>? getPendingNotifications() {
() async {
return await flutterLocalNotificationsPlugin
.pendingNotificationRequests();
};
Future<List<PendingNotificationRequest>?> getPendingNotifications() async {
List<PendingNotificationRequest>? list;
list = await flutterLocalNotificationsPlugin.pendingNotificationRequests();
return list;
}

//鳴っている通知を消す(正確には最新の通知)
//予約の一覧表示
void printPendingNotificationRequests() async {
List<PendingNotificationRequest>? list = await getPendingNotifications();
if (list == null) {
debugPrint("PNR null");
return;
}
if (list.isEmpty) {
debugPrint("■■■ list is emply");
return;
}
String string = "";
for (int i = 0; i < list.length; i++) {
debugPrint("■■■ list[$i] title : ${list[i].title}");
debugPrint("■■■ list[$i] id : ${list[i].id}");
debugPrint("■■■ list[$i] body : ${list[i].body}");
string += "id[$i]:${list[i].id} ";
}
notice(string);
}

//全予約キャンセル
void cancelAllNotifications() async {
List<PendingNotificationRequest>? list = await getPendingNotifications();
if (list == null) return;
//flutterLocalNotificationsPlugin.cancelAll();
//return;
for (int i = 0; i < list.length; i++) {
cancelNotification(list[i].id);
}
}

//鳴っている通知を消す(正確には最新の通知)//デバッグ用
void resetNotification() {
if (_notificationId != null) {
flutterLocalNotificationsPlugin.cancel(_notificationId!); // 通知をキャンセル
Expand All @@ -99,14 +130,17 @@ class RingingAlarm {
}

//指定のidの通知を消す
void delateNotification(int? nId) {
void cancelNotification(int? nId) {
if (nId != null) {
flutterLocalNotificationsPlugin.cancel(nId); // 通知をキャンセル
debugPrint("■■■ cancel id : $nId");
}
/*
_isTimerActive = false; // リセット
nId = null; // リセット
_pausedTime = null;
_notificationOnceFlag = false;
*/
}

// タイマーを開始する
Expand Down Expand Up @@ -147,22 +181,22 @@ class RingingAlarm {
}
}

/// タイマー終了をローカル通知。実質メイン
/// タイマー終了をローカル通知。こちらは使わない
int _scheduleLocalNotification(Duration duration) {
int notificationId =
DateTime.now().hashCode; //現在時刻から生成しているが、通知を管理するIDを指定できる
flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(
android:
AndroidInitializationSettings('@mipmap/ic_launcher'), //通知アイコン
iOS: IOSInitializationSettings()),
onSelectNotification: (payload) {
//通知をタップされた時に行う処理
StartUpProcess().startUp();
StartUpProcess().startUp(notificationId);
debugPrint(
'flutterLocalNotificationsPlugin.initialize.${payload.toString()}');
},
);
int notificationId =
DateTime.now().hashCode; //現在時刻から生成しているが、通知を管理するIDを指定できる
DateTime tzDT = tz.TZDateTime.now(tz.local).add(duration);
flutterLocalNotificationsPlugin.zonedSchedule(
notificationId, //通知のID
Expand All @@ -188,4 +222,84 @@ class RingingAlarm {
debugPrint("■■■ from ${formatTime(tz.TZDateTime.now(tz.local))}");
return notificationId;
}

InitializationSettings initializationSettings = const InitializationSettings(
android: AndroidInitializationSettings('@mipmap/ic_launcher'), //通知アイコン
iOS: IOSInitializationSettings());

NotificationDetails notificationDetails = const NotificationDetails(
android: AndroidNotificationDetails('Alarm2022', 'Alarm2022',
channelDescription: 'Alarm2022 by OUCC Hackathon group-A',
importance: Importance.high,
priority: Priority.high,
//https://esffects.net/361.html からとってきた音源。
//alarm2022\android\app\src\main\res\raw\simple_alarm_music.mp3 に配置。
sound: RawResourceAndroidNotificationSound('simple_alarm_music'),
fullScreenIntent: true),
iOS: IOSNotificationDetails());

/// タイマー終了をローカル通知。日時指定
int scheduleNotification(int notificationId, DateTime datetime) {
flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onSelectNotification: (payload) {
//通知をタップされた時に行う処理
StartUpProcess().startUp(notificationId);
scheduleNotificationSnooze(notificationId);
debugPrint(
'flutterLocalNotificationsPlugin.initialize.${notificationId.toString()}');
},
);
tz.TZDateTime tzDT = tz.TZDateTime.from(datetime, tz.local);
flutterLocalNotificationsPlugin.zonedSchedule(
notificationId, //通知のID
'Time is over', //通知のタイトル
'Wake up! It\'s ${formatTime(tzDT)}', //通知の本文
tzDT, //通知の予約時間
notificationDetails,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
androidAllowWhileIdle: true);
debugPrint("■■■Scheduled for ${formatTime(tzDT)}");
debugPrint("■■■ from ${formatTime(tz.TZDateTime.now(tz.local))}");
debugPrint("■■■ from ${formatTime(DateTime.now())}");
return notificationId;
}

/// タイマー終了をローカル通知。スヌーズ
int scheduleNotificationSnooze(int notificationId) {
flutterLocalNotificationsPlugin.initialize(
initializationSettings,
onSelectNotification: (payload) {
//通知をタップされた時に行う処理
StartUpProcess().startUp(notificationId);
debugPrint(
'flutterLocalNotificationsPlugin.initialize.${notificationId.toString()}');
},
);
flutterLocalNotificationsPlugin.periodicallyShow(
notificationId, //通知のID
'Time is already over', //通知のタイトル
'This is Snooze ${formatTime(DateTime.now())}', //通知の本文
RepeatInterval.everyMinute, //通知の予約時間
notificationDetails,
androidAllowWhileIdle: true);
debugPrint("■■■ ${formatTime(DateTime.now())} Scheduled Snooze");
return notificationId;
}

/// タイマー終了をローカル通知。実機デバッグ用の即時String通知
int notice(String string) {
int notificationId = -1;
flutterLocalNotificationsPlugin.initialize(
initializationSettings,
);
flutterLocalNotificationsPlugin.show(
notificationId, //通知のID
'Notice (debug)', //通知のタイトル
string, //通知の本文
notificationDetails,
);
return notificationId;
}
}
80 changes: 28 additions & 52 deletions lib/model/startup_process_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,40 @@ import 'ringing_alarm_model.dart';

class StartUpProcess {
//このクラスでこれだけがアプリ起動時に呼ばれる
void startUp() {
RingingAlarm ringingAlarm = RingingAlarm();
int? ringingId;
void startUp(int? nId) {
bool? isClearedMission;
//まず通知の状態を取得
List<int>? notificationIds = idOfRingingNowAlarm();
//鳴っている通知を止める
if (notificationIds != null) {
for (var nId in notificationIds) {
//鳴ってるidを取得
ringingId = nId;
}
}
debugPrint("startUp");

isClearedMission = null;
//鳴ってる通知の設定に従って小機能の呼び出し
if (ringingId != null) {
isClearedMission = startAMiniFunc();
}
//クリアしたなら通知消去
if (isClearedMission != null && isClearedMission) {
ringingAlarm.delateNotification(ringingId);
if (nId != null) {
startAMiniFunc().then((value) {
isClearedMission = value;
//クリアしたなら予約キャンセル
if (isClearedMission != null && isClearedMission!) {
RingingAlarm().cancelNotification(nId);
}
});
}
}

///現在鳴っている通知のIdを返す。
///- 鳴っていなかったらnullを返す。
///- アプリ起動時に使用予定
List<int>? idOfRingingNowAlarm() {
List<int>? notificationIds;
//アラームの情報の保存とかができてから詰める

return notificationIds;
}

///小機能に移る。情報の保存できてから引数とか追加
bool? startAMiniFunc() {
bool? isClearedMission;
//なんか非同期のラムダ式がうまくいかなかった(呼び出されていない?)ので
//変なことになっていますが、気にしないでください。(修正募集)
Future<void> _a() async {
isClearedMission = await Navigator.of(CurrentContext.context!).push(
MaterialPageRoute(builder: (context) {
//ランダムで小機能に移る。実際は保存した設定を参照
switch (0) {
default:
//こんな感じでswitch-caseで分岐
//ここを移動先のクラスに変更
//そのクラスから戻るときは
//Navigator.of(context).pop(成功したかのbool);
//を使って成功か否かを返してもらう
return const NewPageTemp(
title: 'New Page Temp from startAMiniPage');
}
}),
);
}

_a();
return isClearedMission;
Future<bool?> startAMiniFunc() async {
return await Navigator.of(CurrentContext.context!).push(
MaterialPageRoute(builder: (context) {
//実際は保存した設定を参照し、小機能を動かす
switch (0) {
default:
//こんな感じでswitch-caseで分岐
//ここを移動先のクラスに変更
//そのクラスから戻るときは
//Navigator.of(context).pop(成功したかのbool);
//を使って成功か否かを返してもらう
return const NewPageTemp(
title: 'New Page Temp from startAMiniPage');
}
}),
);
}
}

Expand Down
41 changes: 41 additions & 0 deletions lib/view/ringing_alarm_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class _RingingAlarmTestPageState extends State<RingingAlarmTestPage>
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
setupRingingAlarm();
//現在時刻表示用だが画面の更新処理も担っている
_clockTimer =
Timer.periodic(const Duration(milliseconds: 100), (Timer clockTimer) {
Expand Down Expand Up @@ -114,6 +115,46 @@ class _RingingAlarmTestPageState extends State<RingingAlarmTestPage>
child: const Text("Reset"),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
//指定時刻にアラームをセット
heroTag: 'set_alarm_button',
onPressed: () {
_ringingAlarm.scheduleNotification(
0,
//時刻指定
DateTime.now().add(const Duration(seconds: 10)));
},
child: const Text("Set"),
),
FloatingActionButton(
//予約表示
heroTag: 'print_PNR_button',
onPressed: () {
_ringingAlarm.printPendingNotificationRequests();
},
child: const Text("PNR"),
),
FloatingActionButton(
//全キャンセル
heroTag: 'cancel_all_button',
onPressed: () {
_ringingAlarm.cancelAllNotifications();
},
child: const Text("Cancel All"),
),
FloatingActionButton(
//通知でデバッグ表示
heroTag: 'notice_button',
onPressed: () {
_ringingAlarm.notice("this is just a debug");
},
child: const Text("Notice"),
),
],
)
]));
}
Expand Down

0 comments on commit b22e700

Please sign in to comment.