Mobile applications often require the ability to schedule notifications for various purposes, such as reminding users about upcoming events, delivering time-sensitive information, or encouraging continued app engagement. Flutter provides developers with several options for implementing scheduled notifications. This blog post explores how to schedule notifications effectively in Flutter using the flutter_local_notifications
plugin and other relevant tools.
Why Schedule Notifications in Flutter?
- User Engagement: Encourage users to return to your app with timely reminders and updates.
- Event Reminders: Notify users of upcoming events or appointments.
- Timely Information: Deliver important information at specific times.
- Improved UX: Provide value to users at the right moments, enhancing their overall experience.
Setting Up Flutter Local Notifications
To get started with scheduling notifications, we’ll use the flutter_local_notifications
plugin. This plugin provides a way to display local notifications on Android and iOS platforms.
Step 1: Add Dependencies
First, add the flutter_local_notifications
and timezone
packages to your pubspec.yaml
file:
dependencies:
flutter_local_notifications: ^16.3.2
timezone: ^0.9.2
rxdart: ^0.27.7 # Required by flutter_local_notifications on some platforms
Then, run flutter pub get
to install the dependencies.
Step 2: Configure Android Settings
For Android, you need to specify a notification icon in the AndroidManifest.xml
file. Place your notification icon (e.g., ic_notification.png
) in the android/app/src/main/res/drawable
directory, and add the following meta-data tag inside the <application>
tag:
Step 3: Configure iOS Settings
For iOS, you need to request authorization to display notifications. Add the following to your AppDelegate.swift
or AppDelegate.m
:
Swift:
import FlutterLocalNotifications
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Objective-C:
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
#import <FlutterLocalNotificationsPlugin.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[FlutterLocalNotificationsPlugin setPluginRegistrantCallback:^(NSObject<FlutterPluginRegistry>* registry) {
[GeneratedPluginRegistrant registerWithRegistry:registry];
}];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
Also, ensure you have requested notification permissions. Add the following keys in your Info.plist
file:
<key>NSUserNotificationAlertSoundKey</key>
<string>Default</string>
<key>NSAppleEventsUsageDescription</key>
<string>This app uses notification to alert you for important event</string>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
Step 4: Initialize FlutterLocalNotificationsPlugin
Initialize the FlutterLocalNotificationsPlugin
in your Flutter app. Create a method to handle this:
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
import 'package:flutter/material.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
Future<void> initializeNotifications() async {
// Initialize timezone
tz.initializeTimeZones();
// Android initialization settings
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('ic_notification');
// iOS initialization settings
const DarwinInitializationSettings initializationSettingsIOS =
DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true);
// General initialization settings
const InitializationSettings initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsIOS,
);
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeNotifications();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Notification Scheduler',
home: Scaffold(
appBar: AppBar(
title: Text('Notification Scheduler'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
scheduleNotification();
},
child: Text('Schedule Notification'),
),
),
),
);
}
}
Scheduling Notifications
Now, let’s look at how to schedule notifications using the flutter_local_notifications
plugin.
Scheduling a Simple Notification
Future<void> scheduleNotification() async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'your_channel_id',
'your_channel_name',
channelDescription: 'your_channel_description',
importance: Importance.max,
priority: Priority.high,
ticker: 'ticker',
);
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics, iOS: DarwinNotificationDetails());
await flutterLocalNotificationsPlugin.show(
0,
'Scheduled Title',
'Scheduled Body',
platformChannelSpecifics,
payload: 'item x',
);
}
Scheduling a Notification for a Specific Time
To schedule a notification at a specific time, use the zonedSchedule
method.
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
Future<void> 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,
matchDateTimeComponents: DateTimeComponents.time);
}
Key points:
- Timezone Setup:
tz.initializeTimeZones()
must be called to initialize timezones. tz.TZDateTime.now(tz.local)
: Gets the current time in the local timezone.add(const Duration(seconds: 5))
: Schedules the notification 5 seconds from the current time. Adjust the duration as needed.androidAllowWhileIdle: true
: Allows the notification to be delivered even when the device is in doze mode (Android).UILocalNotificationDateInterpretation.absoluteTime
: Ensure the notification is interpreted as an absolute time.
Handling Notification Actions
You might want to perform actions when a user taps on a notification. The flutter_local_notifications
plugin allows you to set a payload that can be used to navigate to a specific screen or perform a specific action.
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeNotifications();
// Handle notification tap
flutterLocalNotificationsPlugin.initialize(
const InitializationSettings(
android: AndroidInitializationSettings('ic_notification'),
iOS: DarwinInitializationSettings(),
),
onDidReceiveNotificationResponse: (NotificationResponse notificationResponse) async {
// Handle the payload here
print('Notification payload: ${notificationResponse.payload}');
},
);
runApp(MyApp());
}
Advanced Scheduling Techniques
Repeat Interval Notifications
You can also schedule notifications to repeat at a specific interval. Use the periodicallyShow
method.
Future<void> showNotificationPeriodically() async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails('repeating channel id',
'repeating channel name',
channelDescription: 'repeating description');
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics, iOS: DarwinNotificationDetails());
await flutterLocalNotificationsPlugin.periodicallyShow(0, 'Repeating Title',
'Repeating Body', RepeatInterval.everyMinute, platformChannelSpecifics,
androidAllowWhileIdle: true);
}
Daily Scheduled Notifications
To schedule a notification for the same time every day, use the zonedSchedule
method along with matchDateTimeComponents
.
Future<void> scheduleDailyNotification() async {
await flutterLocalNotificationsPlugin.zonedSchedule(
0,
'Daily Scheduled Title',
'Daily Scheduled Body',
_nextInstanceOfTenAM(),
const NotificationDetails(
android: AndroidNotificationDetails(
'daily_channel_id', 'daily_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, 0);
if (scheduledDate.isBefore(now)) {
scheduledDate = scheduledDate.add(const Duration(days: 1));
}
return scheduledDate;
}
Best Practices for Scheduling Notifications
- Request Permissions: Always request notification permissions from the user, especially on iOS.
- Handle Timezones: Use the
timezone
package to handle timezones correctly and avoid issues with notification scheduling. - Test Thoroughly: Test your notification scheduling on different devices and platforms to ensure they are delivered as expected.
- Respect User Preferences: Allow users to customize their notification preferences within your app.
- Graceful Handling: Ensure your app handles cases where notifications cannot be delivered (e.g., user has disabled notifications).
Conclusion
Scheduling notifications in Flutter is a powerful way to enhance user engagement and provide timely information. By leveraging the flutter_local_notifications
plugin and following best practices, you can effectively schedule notifications that deliver value to your users at the right moments. Whether you need to schedule simple reminders or complex recurring notifications, Flutter provides the tools and flexibility you need to implement robust notification scheduling in your mobile applications. This comprehensive guide covers essential aspects of scheduling notifications in Flutter, helping you create a more engaging and user-friendly app experience.