Skip to content

Commit

Permalink
Update changelog & readme + add minor improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
gdelataillade committed Nov 16, 2023
1 parent 22671f1 commit dabeb1d
Show file tree
Hide file tree
Showing 9 changed files with 27 additions and 46 deletions.
17 changes: 12 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
## 3.0.0
**💥 Breaking Changes**
**🔧 Android installation steps were updated [here](https://github.com/gdelataillade/alarm/blob/main/help/INSTALL-ANDROID.md).**
* Remove [stopOnNotificationOpen] property.
* Make notification mandatory so android foreground services can be used.
* [Android] Refactor alarm to native android services.

## 2.2.0
* [Android] Move alarm service to native code.

## 2.1.0
**Android installation steps were updated.**
**🔧 Android installation steps were updated [here](https://github.com/gdelataillade/alarm/blob/main/help/INSTALL-ANDROID.md).**
* [Android] Add parameter [androidFullScreenIntent] that turns screen on when alarm notification is triggered.
* [Android] Fix 'ring now' alarm delay.
* [Android] Fix fadeDuration cast error.
Expand All @@ -14,7 +21,7 @@
* Refactor set alarm methods.

## 2.0.0
**Breaking Changes**
**💥 Breaking Changes**
* Installation steps were updated in the README. Please make sure to follow them.
* [iOS] Add Background Fetch to periodically make sure alarms are still active in the background.

Expand Down Expand Up @@ -131,7 +138,7 @@
* Add optional [vibrate] parameter, to toggle vibrations when alarm rings.

## 0.2.0
* **Breaking changes**: Add multiple alarm management. Now, you have to provide a unique [id] to [AlarmSettings].
* **💥 Breaking changes**: Add multiple alarm management. Now, you have to provide a unique [id] to [AlarmSettings].
* Update example application.
* [Android] Fix potential delay between notification and alarm sound.

Expand All @@ -155,8 +162,8 @@
* Export [AlarmSettings] model in [Alarm] service so it's not necessary to import it separately anymore.

## 0.1.0
* **Breaking changes**: [Alarm.set] method now takes a [AlarmSettings] as only parameter.
* **Breaking changes**: You will have to create a `StreamSubscription` attached to [Alarm.ringStream.stream] in order to listen to the alarm ringing state now. This way, even if your app was previously killed, your custom callback can still be triggered.
* **💥 Breaking changes**: [Alarm.set] method now takes a [AlarmSettings] as only parameter.
* **💥 Breaking changes**: You will have to create a `StreamSubscription` attached to [Alarm.ringStream.stream] in order to listen to the alarm ringing state now. This way, even if your app was previously killed, your custom callback can still be triggered.
* By default, if an alarm was set and the app is killed, a notification will be shown to warn
the user that the alarm may not ring, with the possibility to reopen the app and automatically reschedule the alarm.
To disable this feature, you can call the method [Alarm.toggleNotificationOnAppKill(false)].
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This plugin offers a straightforward interface to set and cancel alarms on both

## 🔧 Installation steps

Please carefully follow these installation steps. They have been updated for plugin version `2.0.0`.
Please carefully follow these installation steps. They have been updated for plugin version `3.0.0`.

### [iOS Setup](https://github.com/gdelataillade/alarm/blob/feat/ios-background-fetch/help/INSTALL-IOS.md)
### [Android Setup](https://github.com/gdelataillade/alarm/blob/feat/ios-background-fetch/help/INSTALL-ANDROID.md)
Expand Down Expand Up @@ -65,9 +65,7 @@ notificationBody | `String` | The body of the notification.
enableNotificationOnKill | `bool` | Whether to show a notification when application is killed to warn the user that the alarm he set may not ring. Enabled by default.
androidFullScreenIntent | `bool` | Whether to turn screen on when android alarm notification is triggered. Enabled by default.

The notification shown on alarm ring can be disabled simply by ignoring the parameters `notificationTitle` and `notificationBody`. However, if you want a notification to be triggered, you will have to provide **both of them**.

If you enabled `enableNotificationOnKill`, you can chose your own notification title and body by using this method:
If you enabled `enableNotificationOnKill`, you can chose your own notification title and body by using this method before setting your alarms:
```Dart
await Alarm.setNotificationOnAppKillContent(title, body)
```
Expand Down Expand Up @@ -124,6 +122,7 @@ Most common solution is to educate users to disable **battery optimization** set

The more time the app spends in the background, the higher the chance the OS might stop it from running due to memory or battery optimizations. Here's how you can optimize:

- **Battery Optimization**: Educate users to disable battery optimization on Android.
- **Regular App Usage**: Encourage users to open the app at least once a day.
- **Leverage Background Modes**: Engage in activities like weather API calls that keep the app active in the background.
- **User Settings**: Educate users to refrain from using 'Do Not Disturb' and 'Low Power Mode' when they're expecting the alarm to ring.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ class AlarmPlugin: FlutterPlugin, MethodCallHandler {
val id = call.argument<Int>("id")!!
val delayInSeconds = call.argument<Int>("delayInSeconds")!!

Log.d("AlarmPlugin", "delay is $delayInSeconds seconds")

val alarmIntent = createAlarmIntent(context, call, id)

if (delayInSeconds <= 5) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ class NotificationOnKillService: Service() {
override fun onBind(intent: Intent?): IBinder? {
return null
}
}
}
2 changes: 1 addition & 1 deletion example/lib/screens/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class _ExampleAlarmHomeScreenState extends State<ExampleAlarmHomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('alarm 2.2.0')),
appBar: AppBar(title: const Text('alarm 3.0.0')),
body: SafeArea(
child: alarms.isNotEmpty
? ListView.separated(
Expand Down
2 changes: 0 additions & 2 deletions example/lib/screens/shortcut_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class _ExampleAlarmHomeShortcutButtonState

setState(() => showMenu = false);

alarmPrint(dateTime.toString());

final alarmSettings = AlarmSettings(
id: DateTime.now().millisecondsSinceEpoch % 10000,
dateTime: dateTime,
Expand Down
22 changes: 1 addition & 21 deletions lib/service/notification.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,6 @@ class AlarmNotification {
return false;
}

Future<bool> requestExactAlarmsPermission() async {
if (defaultTargetPlatform == TargetPlatform.android) {
final res = await localNotif
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.requestExactAlarmsPermission();

return res ?? false;
}
return true;
}

tz.TZDateTime nextInstanceOfTime(DateTime dateTime) {
final now = DateTime.now();

Expand Down Expand Up @@ -115,11 +103,6 @@ class AlarmNotification {
alarmPrint('Notification permission not granted');
}

final hasExactAlarmPermission = await requestExactAlarmsPermission();
if (!hasExactAlarmPermission) {
alarmPrint('Exact alarm permission not granted');
}

try {
await localNotif.zonedSchedule(
id,
Expand All @@ -141,8 +124,5 @@ class AlarmNotification {

/// Cancels notification. Called when the alarm is cancelled or
/// when an alarm is overriden.
Future<void> cancel(int id) async {
await localNotif.cancel(id);
alarmPrint('Notification with id $id canceled');
}
Future<void> cancel(int id) => localNotif.cancel(id);
}
17 changes: 8 additions & 9 deletions lib/src/android_alarm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import 'package:alarm/alarm.dart';
import 'package:alarm/service/storage.dart';
import 'package:flutter/services.dart';

/// For Android support, [AndroidAlarmManager] is used to trigger a callback
/// when the given time is reached. The callback will run in an isolate if app
/// is in background.
/// Uses method channel to interact with the native platform.
class AndroidAlarm {
static const platform = MethodChannel('com.gdelataillade.alarm/alarm');

Expand All @@ -27,15 +25,15 @@ class AndroidAlarm {
}
}

/// Creates isolate communication channel and set alarm at given [dateTime].
/// Schedules a native alarm with given [alarmSettings] with its notification.
static Future<bool> set(
AlarmSettings settings,
void Function()? onRing,
) async {
try {
final delay = settings.dateTime.difference(DateTime.now());

final res = await platform.invokeMethod(
await platform.invokeMethod(
'setAlarm',
{
'id': settings.id,
Expand All @@ -50,7 +48,6 @@ class AndroidAlarm {
'fullScreenIntent': settings.androidFullScreenIntent,
},
);
alarmPrint('[DEV] setAlarm method channel invoked, returned: $res');
} catch (e) {
throw AlarmException('nativeAndroidAlarm error: $e');
}
Expand All @@ -64,33 +61,35 @@ class AndroidAlarm {
'description': AlarmStorage.getNotificationOnAppKillBody(),
},
);
alarmPrint('NotificationOnKillService enabled with success');
} catch (e) {
throw AlarmException('NotificationOnKillService error: $e');
}
}

alarmPrint('[DEV] Alarm with id ${settings.id} scheduled');

return true;
}

/// Sends the message `stop` to the isolate so the audio player
/// can stop playing and dispose.
static Future<bool> stop(int id) async {
final res = await platform.invokeMethod('stopAlarm', {'id': id});
alarmPrint('[DEV] stopAlarm method channel invoked, returned: $res');
if (res) alarmPrint('[DEV] Alarm with id $id stopped');
if (!hasOtherAlarms) stopNotificationOnKillService();
return res;
}

/// Checks if the alarm with given [id] is ringing.
static Future<bool> isRinging(int id) async {
final res = await platform.invokeMethod('isRinging', {'id': id});
return res;
}

/// Disable the notification on kill service.
static Future<void> stopNotificationOnKillService() async {
try {
await platform.invokeMethod('stopNotificationOnKillService');
alarmPrint('NotificationOnKillService disabled with success');
} catch (e) {
throw AlarmException('NotificationOnKillService error: $e');
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/ios_alarm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class IOSAlarm {
) ??
false;

if (res) alarmPrint('Alarm with id $id stopped with success');
if (res) alarmPrint('Alarm with id $id stopped');

return res;
}
Expand Down

0 comments on commit dabeb1d

Please sign in to comment.