11 Commits
4 changed files with 95 additions and 56 deletions

No files matched your search

+6 -8
View File
@@ -3,13 +3,14 @@
xmlns:tools="http://schemas.android.com/tools"
>
<!-- Allow notifications to work. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
<!--
<!-- Allow alarms to work. -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.VIBRATE"/>
@@ -25,10 +26,9 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
-->
<application
android:label="sunset_alarm"
android:label="Sunset Alarm"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
@@ -59,6 +59,7 @@
android:name="flutterEmbedding"
android:value="2" />
<!-- Allow notifications to work. -->
<receiver
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver"
android:enabled="true" />
@@ -74,16 +75,14 @@
</intent-filter>
</receiver>
<!--
<!-- Allow alarms to work. -->
<service
android:name="com.gdelataillade.alarm.AlarmService"
android:foregroundServiceType="mediaPlayback"
android:exported="false" />
<receiver
android:name="com.gdelataillade.alarm.AlarmBroadcastReceiver"
android:exported="false" />
<receiver
android:name="com.gdelataillade.alarm.BootBroadcastReceiver"
android:enabled="false"
@@ -92,7 +91,6 @@
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name="dev.fluttercommunity.plus.androidalarmmanager.AlarmService"
android:permission="android.permission.BIND_JOB_SERVICE"
@@ -111,7 +109,7 @@
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
-->
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
+16
View File
@@ -0,0 +1,16 @@
AuthorName: 'Chad Michael "Hyperling" Greenwood'
AuthorEmail: 'me@hyperling.com'
AuthorWebSite: 'https://hyperling.com/about/'
Donate: 'https://hyperling.com/donate/'
Liberapay: 'HyperVegan'
Bitcoin: 'bc1qsfe8dkvry3d34kztz449gkq67wq8fu2nkgfkh0'
Litecoin: 'ltc1qavmpu5d6ljntxsd6jj548m4yys83zwscl0dzkx'
IssueTracker: 'https://hyperling.com/contact/'
Categories:
- fdroid
- hyperling
- utilities
Name: Sunset Timer
Summary: 'Play a notification at your chosen time before sunset.'
SourceCode: 'https://git.hyperling.com/me/flutter-sunset-alarm/'
WebSite: 'https://hyperling.com/apps/#sunset'
+72 -47
View File
@@ -6,16 +6,27 @@ 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';
import 'package:alarm/alarm.dart';
import 'dart:convert';
/// TBD:
/// v0.2.1
/// - Fix time to get 0 prefixed if before 10:00 (5:30 becomes 05:30).
/// - Fix time to validate properly rather than allowing garbage (error 530).
/// v0.3.0
/// - Add sunrise section and change app name to Sunshine Alarm?
/// v1.0.0
/// - Follow system theme rather than using a custom theme.
/// v1.0.1
/// - Use a timepicker if the user clicks on the sunset/sunrise time.
/// :TBD
void main() async {
WidgetsFlutterBinding.ensureInitialized();
tz.initializeTimeZones();
//await Alarm.init();
await Alarm.init();
runApp(const SunsetAlarmApp());
}
@@ -55,6 +66,9 @@ class _HomeScreenState extends State<HomeScreen> {
int _minutesBefore = 30;
bool _loading = false;
String? _sunsetErrorText = null;
String? _minuteErrorText = null;
static const _alarmId = 1001;
@override
@@ -232,7 +246,7 @@ class _HomeScreenState extends State<HomeScreen> {
'Alarm set for ${alarmTime.hour.toString().padLeft(2, '0')}:${alarmTime.minute.toString().padLeft(2, '0')} (app must stay open)',
);
} else if (Platform.isAndroid) {
/*** Notifcation Method - Works ***/
/*** Notifcation Method - Works *** /
// Android: use zonedSchedule (works in background)
final tzAlarm = tz.TZDateTime.from(alarmTime, tz.local);
const androidDetails = AndroidNotificationDetails(
@@ -258,22 +272,22 @@ class _HomeScreenState extends State<HomeScreen> {
debugPrint('DEBUG: ${_notifications.toString()}');
// End Notification Method ***/
/*** Alarm Method - WIP *** /
/*** Alarm Method - WIP ***/
// Schedule:
final settings = AlarmSettings(
id: 42,
dateTime: alarmTime, // your computed sunset time
assetAudioPath: 'assets/alarm.mp3', // put an alarm sound in assets/
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,
fadeDuration: Duration(seconds: 5),
//volume: 0.8, // use default rather than custom
fadeDuration: Duration(seconds: 60),
),
notificationSettings: const NotificationSettings(
notificationSettings: NotificationSettings(
title: 'Sunset Alarm',
body: 'The sun sets now. Time to get ready!',
body: 'Sun is setting in ${_minutesBefore} minute(s)!',
stopButton: 'Dismiss',
),
);
@@ -292,7 +306,11 @@ class _HomeScreenState extends State<HomeScreen> {
} else {
_alarmTimer?.cancel();
if (!Platform.isLinux) {
await _notifications.cancel(id: _alarmId);
// Notification Method
//await _notifications.cancel(id: _alarmId);
// Alarm Method
await Alarm.stop(_alarmId);
}
_showSnack('Alarm cancelled.');
}
@@ -360,7 +378,7 @@ class _HomeScreenState extends State<HomeScreen> {
const SizedBox(width: 8),
IconButton.filledTonal(
icon: const Icon(Icons.my_location),
tooltip: 'Get GPS location',
tooltip: 'Get GPS Location',
onPressed: _getGpsLocation,
),
],
@@ -379,7 +397,7 @@ class _HomeScreenState extends State<HomeScreen> {
child: TextField(
controller: _sunsetController,
decoration: const InputDecoration(
labelText: 'Sunset time (HH:MM)',
labelText: 'Sunset Time (HH:MM)',
border: OutlineInputBorder(),
),
onChanged: (_) => _savePrefs(),
@@ -395,55 +413,62 @@ class _HomeScreenState extends State<HomeScreen> {
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.cloud_done_outlined),
tooltip: 'Fetch sunset from Open-Meteo',
tooltip: 'Fetch Sunset Time from Open-Meteo',
onPressed: _loading ? null : _fetchSunset,
),
],
),
const SizedBox(height: 16),
// --- Minutes before ---
const Text(
'Alert Before Sunset',
'Alert',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
// --- Minutes before ---
Row(
children: [
const Text('Minutes before: '),
SizedBox(
width: 80,
child: TextField(
controller: _minutesController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border: OutlineInputBorder(),
if (!_alarmEnabled)
Expanded(
child: TextField(
controller: _minutesController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Minutes Before Sunset',
errorText: _minuteErrorText,
),
onChanged: (v) {
final val = int.tryParse(v);
setState(() {
if (val != null) {
_minuteErrorText = null;
_minutesBefore = val;
} else {
_minuteErrorText = 'Invalid Minute Value';
}
});
},
),
onChanged: (v) {
final val = int.tryParse(v);
if (val != null && val >= 0) {
_minutesBefore = val;
} else {
_showSnack('Invalid Minute Value');
}
},
),
// --- Toggle ---
Expanded(
child: SwitchListTile(
//title: const Text('Enable Sunset Alarm'),
title: Text(_alarmEnabled ? 'Sunset Alarm Enabled' : ''),
subtitle: Text(
_alarmEnabled
? 'Will alert ${_minutesBefore} min before sunset. ($_alarmDisplayTime)'
: '',
),
value: _alarmEnabled,
onChanged: _toggleAlarm,
),
),
],
),
const SizedBox(height: 24),
// --- Toggle ---
SwitchListTile(
title: const Text('Enable Sunset Alarm'),
subtitle: Text(
_alarmEnabled
? 'Will alert ${_minutesBefore} min before sunset. ($_alarmDisplayTime)'
: 'Alarm is off',
),
value: _alarmEnabled,
onChanged: _toggleAlarm,
),
],
),
),
+1 -1
View File
@@ -1,7 +1,7 @@
name: sunset_alarm
description: "Set an alarm to go off a specified time before sunset."
publish_to: 'none'
version: 0.1.2
version: 0.2.0
environment:
sdk: ^3.7.2