Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f0b69d6cf | ||
|
|
dc97081517 | ||
|
|
8167c748ff | ||
|
|
4926c869b9 |
No files matched your search
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 216 B |
|
After Width: | Height: | Size: 173 B |
|
After Width: | Height: | Size: 284 B |
|
After Width: | Height: | Size: 443 B |
|
After Width: | Height: | Size: 565 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 816 B |
|
Before Width: | Height: | Size: 910 B After Width: | Height: | Size: 456 B |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 818 B After Width: | Height: | Size: 626 B |
|
Before Width: | Height: | Size: 602 B After Width: | Height: | Size: 334 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1022 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 586 B |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 946 B |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 6.8 KiB |
@@ -6,6 +6,7 @@ import 'package:geolocator/geolocator.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:timezone/data/latest_all.dart' as tz;
|
||||
import 'package:timezone/timezone.dart' as tz;
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:alarm/alarm.dart';
|
||||
|
||||
@@ -25,6 +26,9 @@ void main() async {
|
||||
runApp(const SunsetAlarmApp());
|
||||
}
|
||||
|
||||
const ANDROID_USE_NOTIF = false;
|
||||
const ANDROID_USE_ALARM = !ANDROID_USE_NOTIF;
|
||||
|
||||
class SunsetAlarmApp extends StatelessWidget {
|
||||
const SunsetAlarmApp({super.key});
|
||||
|
||||
@@ -189,6 +193,10 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
} finally {
|
||||
setState(() => _loading = false);
|
||||
}
|
||||
|
||||
if (_alarmEnabled) {
|
||||
_scheduleAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
Timer? _alarmTimer;
|
||||
@@ -251,52 +259,59 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
'Alarm Enabled @ ${alarmTime.hour.toString().padLeft(2, '0')}:${alarmTime.minute.toString().padLeft(2, '0')} (App Must Stay Open!)',
|
||||
);
|
||||
} else if (Platform.isAndroid) {
|
||||
/*** Notifcation Method - Works *** /
|
||||
// Android: use zonedSchedule (works in background)
|
||||
final tzAlarm = tz.TZDateTime.from(alarmTime, tz.local);
|
||||
const androidDetails = AndroidNotificationDetails(
|
||||
'sunset_alarm',
|
||||
'Sunset Alarm',
|
||||
channelDescription: 'Alarm X minutes before sunset',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
fullScreenIntent: true,
|
||||
category: AndroidNotificationCategory.alarm,
|
||||
);
|
||||
await _notifications.zonedSchedule(
|
||||
id: _alarmId,
|
||||
title: 'Sunset in ${_minutesBefore} min',
|
||||
body: 'The sun sets at $sunsetText. Time to get ready!',
|
||||
scheduledDate: tzAlarm,
|
||||
notificationDetails: const NotificationDetails(android: androidDetails),
|
||||
androidScheduleMode: AndroidScheduleMode.alarmClock,
|
||||
);
|
||||
_showSnack('Alarm scheduled!');
|
||||
debugPrint('DEBUG: Alarm time: ${tzAlarm.toString()}');
|
||||
debugPrint('DEBUG: Current time: ${DateTime.now().toUtc().toString()}');
|
||||
debugPrint('DEBUG: ${_notifications.toString()}');
|
||||
/*** Notifcation Method - Works ***/
|
||||
if (ANDROID_USE_NOTIF) {
|
||||
// Android: use zonedSchedule (works in background)
|
||||
final tzAlarm = tz.TZDateTime.from(alarmTime, tz.local);
|
||||
const androidDetails = AndroidNotificationDetails(
|
||||
'sunset_alarm',
|
||||
'Sunset Alarm',
|
||||
channelDescription: 'Alarm X minutes before sunset',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
fullScreenIntent: true,
|
||||
category: AndroidNotificationCategory.alarm,
|
||||
);
|
||||
await _notifications.zonedSchedule(
|
||||
id: _alarmId,
|
||||
title: 'Sunset in ${_minutesBefore} min',
|
||||
body: 'The sun sets at $sunsetText. Time to get ready!',
|
||||
scheduledDate: tzAlarm,
|
||||
notificationDetails: const NotificationDetails(
|
||||
android: androidDetails,
|
||||
),
|
||||
androidScheduleMode: AndroidScheduleMode.alarmClock,
|
||||
);
|
||||
_showSnack('Alarm scheduled!');
|
||||
debugPrint('DEBUG: Alarm time: ${tzAlarm.toString()}');
|
||||
debugPrint('DEBUG: Current time: ${DateTime.now().toUtc().toString()}');
|
||||
debugPrint('DEBUG: ${_notifications.toString()}');
|
||||
}
|
||||
// End Notification Method ***/
|
||||
|
||||
/*** Alarm Method - WIP ***/
|
||||
// Schedule:
|
||||
final settings = AlarmSettings(
|
||||
id: _alarmId,
|
||||
dateTime: alarmTime,
|
||||
//assetAudioPath: 'assets/alarm.mp3', // use default rather than custom
|
||||
loopAudio: true, // keeps ringing until dismissed
|
||||
vibrate: true,
|
||||
androidFullScreenIntent: true, // wakes screen like clock app
|
||||
volumeSettings: VolumeSettings.fade(
|
||||
//volume: 0.8, // use default rather than custom
|
||||
fadeDuration: Duration(seconds: 60),
|
||||
),
|
||||
notificationSettings: NotificationSettings(
|
||||
title: 'Sunset Alarm',
|
||||
body: 'Sun is setting in ${_minutesBefore} minute(s)!',
|
||||
stopButton: 'Dismiss',
|
||||
),
|
||||
);
|
||||
await Alarm.set(alarmSettings: settings);
|
||||
if (ANDROID_USE_ALARM) {
|
||||
// Schedule:
|
||||
final settings = AlarmSettings(
|
||||
id: _alarmId,
|
||||
dateTime: alarmTime,
|
||||
//assetAudioPath: 'assets/alarm.mp3', // use default rather than custom
|
||||
loopAudio: true, // keeps ringing until dismissed
|
||||
vibrate: true,
|
||||
androidFullScreenIntent: true, // wakes screen like clock app
|
||||
volumeSettings: VolumeSettings.fade(
|
||||
//volume: 0.8, // use default rather than custom
|
||||
fadeDuration: Duration(seconds: 60),
|
||||
),
|
||||
notificationSettings: NotificationSettings(
|
||||
title: 'Sunset Alarm',
|
||||
body: 'Sun is setting in ${_minutesBefore} minute(s)!',
|
||||
stopButton: 'Dismiss',
|
||||
icon: 'ic_notification',
|
||||
),
|
||||
);
|
||||
await Alarm.set(alarmSettings: settings);
|
||||
}
|
||||
// End Alarm Method ***/
|
||||
_showSnack('Alarm Scheduled @ ${alarmTime}');
|
||||
} else {
|
||||
@@ -313,10 +328,10 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
_alarmTimer?.cancel();
|
||||
if (!Platform.isLinux) {
|
||||
// Notification Method
|
||||
//await _notifications.cancel(id: _alarmId);
|
||||
if (ANDROID_USE_NOTIF) await _notifications.cancel(id: _alarmId);
|
||||
|
||||
// Alarm Method
|
||||
await Alarm.stop(_alarmId);
|
||||
if (ANDROID_USE_ALARM) await Alarm.stop(_alarmId);
|
||||
}
|
||||
_showSnack('Alarm Cancelled');
|
||||
}
|
||||
@@ -434,6 +449,9 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
_sunsetController.text,
|
||||
),
|
||||
);
|
||||
if (_alarmEnabled) {
|
||||
_scheduleAlarm();
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -466,9 +484,6 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
onPressed: () {
|
||||
if (!_loading) {
|
||||
_fetchSunset();
|
||||
if (_alarmEnabled) {
|
||||
_scheduleAlarm();
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |