In Flutter, local notifications are a powerful way to engage users even when your app is not in the foreground. Scheduling these notifications to be delivered at specific times or intervals adds another layer of sophistication, allowing you to remind users about important events, tasks, or updates. This post will guide you through the process of scheduling local notifications at specific times or intervals in a Flutter application.
What are Scheduled Notifications?
Scheduled notifications are local notifications that are programmed to appear at a specific time in the future or at recurring intervals. This can be useful for tasks such as reminding users about appointments, delivering daily tips, or alerting them about upcoming events.
Why Schedule Notifications?
- User Engagement: Keep users engaged with timely reminders and updates.
- Personalization: Deliver notifications based on the user’s specific schedule and preferences.
- Improved UX: Provide timely information without requiring the user to constantly open the app.
How to Schedule Notifications in Flutter
To schedule local notifications in Flutter, you can use the flutter_local_notifications
plugin. Here’s how to do it:
Step 1: Add Dependencies
First, add the flutter_local_notifications
and timezone
plugins to your pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
flutter_local_notifications: ^16.3.2
timezone: ^0.9.2
rxdart: ^0.27.7
Run flutter pub get
to install the dependencies.
Step 2: Initialize the Plugin
Initialize the FlutterLocalNotificationsPlugin
in your main.dart
file:
import 'package:flutter/material.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:rxdart/rxdart.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final BehaviorSubject didReceiveLocalNotificationSubject =
BehaviorSubject();
final BehaviorSubject selectNotificationSubject =
BehaviorSubject();
class ReceivedNotification {
ReceivedNotification({
required this.id,
required this.title,
required this.body,
required this.payload,
});
final int id;
final String? title;
final String? body;
final String? payload;
}
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await _configureLocalNotifications();
runApp(MyApp());
}
Future _configureLocalNotifications() async {
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('app_icon');
// iOS settings
final DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
onDidReceiveLocalNotification:
(int id, String? title, String? body, String? payload) async {
didReceiveLocalNotificationSubject.add(ReceivedNotification(
id: id, title: title, body: body, payload: payload));
});
// OS X settings
final MacOSInitializationSettings initializationSettingsMacOS =
MacOSInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false);
final InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
macOS: initializationSettingsMacOS,
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onDidReceiveNotificationResponse: (NotificationResponse details) {
selectNotificationSubject.add(details.payload);
});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Scheduled Notifications'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
child: Text('Schedule Notification'),
onPressed: () {
scheduleNotification();
},
),
ElevatedButton(
child: Text('Schedule Daily 10 AM Notification'),
onPressed: () {
scheduleDailyTenAMNotification();
},
),
ElevatedButton(
child: Text('Schedule Notification After 5 Seconds'),
onPressed: () {
scheduleNotificationAfterFiveSeconds();
},
),
ElevatedButton(
child: Text('Schedule Periodic Notification'),
onPressed: () {
periodicNotification();
},
),
],
),
),
),
);
}
}
Step 3: Scheduling a Notification
Now, define a method to show a notification immediately. In your main.dart add the following function. This displays a notification right after a button is pressed, demonstrating how immediate notifications work:
Future showNotification() async {
const AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails('your channel id', 'your channel name',
channelDescription: 'your channel description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidNotificationDetails);
await flutterLocalNotificationsPlugin.show(
0, 'plain title', 'plain body', platformChannelSpecifics,
payload: 'item x');
}
Step 4: Schedule a Notification for a Specific Time
To schedule a notification for a specific time, use the zonedSchedule
method:
Future scheduleNotification() async {
await flutterLocalNotificationsPlugin.zonedSchedule(
0,
'scheduled title',
'scheduled body',
tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
const NotificationDetails(
android: AndroidNotificationDetails(
'your channel id', 'your channel name',
channelDescription: 'your channel description')),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime);
}
Step 5: Schedule a Daily Notification at a Specific Time
To schedule a daily notification, use the androidAllowWhileIdle: true
parameter along with setting the hour:
Future scheduleDailyTenAMNotification() async {
await flutterLocalNotificationsPlugin.zonedSchedule(
0,
'daily scheduled notification title',
'daily scheduled notification body',
_nextInstanceOfTenAM(),
const NotificationDetails(
android: AndroidNotificationDetails('daily notification channel id',
'daily notification channel name',
channelDescription: 'daily notification description'),
),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
matchDateTimeComponents: DateTimeComponents.time);
}
tz.TZDateTime _nextInstanceOfTenAM() {
final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
tz.TZDateTime scheduledDate = tz.TZDateTime(
tz.local, now.year, now.month, now.day, 10); // 10 AM
if (scheduledDate.isBefore(now)) {
scheduledDate = scheduledDate.add(const Duration(days: 1));
}
return scheduledDate;
}
Step 6: Schedule a Notification after 5 Seconds
To schedule a notification that fires five seconds in the future:
Future scheduleNotificationAfterFiveSeconds() async {
await flutterLocalNotificationsPlugin.zonedSchedule(
0,
'Five Seconds scheduled title',
'Five Seconds scheduled body',
tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
const NotificationDetails(
android: AndroidNotificationDetails('five seconds channel id',
'five seconds channel name',
channelDescription: 'five seconds channel description'),
),
androidAllowWhileIdle: true,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime);
}
Step 7: Period Notification
Schedule notification in every minute interval, this could be 5 minutes or even days based on the given configuration.
Future periodicNotification() async {
const AndroidNotificationDetails androidNotificationDetails =
AndroidNotificationDetails('periodic channel id', 'periodic channel name',
channelDescription: 'periodic channel description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker');
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidNotificationDetails);
await flutterLocalNotificationsPlugin.periodicallyShow(0, 'periodic title',
'periodic body', RepeatInterval.everyMinute, platformChannelSpecifics,
androidAllowWhileIdle: true);
}
Best Practices for Scheduling Notifications
- Request Permission: Always request permission from the user before scheduling notifications, especially on iOS.
- Handle Time Zones: Use the
timezone
package to handle time zones correctly and ensure notifications are delivered at the correct time for the user’s location. - Provide Clear Content: Ensure your notification content is clear and provides value to the user.
- Allow Opt-Out: Provide users with an option to disable or customize notifications.
Conclusion
Scheduling notifications in Flutter can greatly enhance user engagement and provide timely information. By using the flutter_local_notifications
plugin along with the timezone
package, you can schedule notifications at specific times or intervals. Follow best practices to ensure your notifications provide value to users and respect their preferences. Whether you’re reminding users about appointments or delivering daily updates, scheduled notifications can play a key role in your Flutter application.