DEV Community

kanta13jp1
kanta13jp1

Posted on

Flutter Local Notifications — Scheduled and Rich Notifications with flutter_local_notifications

Flutter Local Notifications — Scheduled and Rich Notifications with flutter_local_notifications

No push server needed — local notifications can re-engage users on their own. Here are the key implementation patterns.

Setup

# pubspec.yaml
dependencies:
  flutter_local_notifications: ^17.0.0
  timezone: ^0.9.0
Enter fullscreen mode Exit fullscreen mode
// main.dart
final FlutterLocalNotificationsPlugin notifications =
    FlutterLocalNotificationsPlugin();

Future<void> initNotifications() async {
  tz.initializeTimeZones();
  tz.setLocalLocation(tz.getLocation('America/New_York'));

  const android = AndroidInitializationSettings('@mipmap/ic_launcher');
  const ios = DarwinInitializationSettings(
    requestAlertPermission: true,
    requestBadgePermission: true,
    requestSoundPermission: true,
  );
  await notifications.initialize(
    const InitializationSettings(android: android, iOS: ios),
    onDidReceiveNotificationResponse: (details) {
      handleNotificationTap(details.payload);
    },
  );
}
Enter fullscreen mode Exit fullscreen mode

Immediate Notification

Future<void> showNotification({
  required String title,
  required String body,
  String? payload,
}) async {
  const details = NotificationDetails(
    android: AndroidNotificationDetails(
      'default_channel',
      'Default Notifications',
      importance: Importance.high,
      priority: Priority.high,
    ),
    iOS: DarwinNotificationDetails(),
  );
  await notifications.show(0, title, body, details, payload: payload);
}
Enter fullscreen mode Exit fullscreen mode

Scheduled Notification (Daily Reminder)

Future<void> scheduleDailyReminder({
  required int id,
  required String title,
  required String body,
  required Time time,
}) async {
  await notifications.zonedSchedule(
    id,
    title,
    body,
    _nextInstanceOfTime(time),
    const NotificationDetails(
      android: AndroidNotificationDetails('reminder', 'Reminders'),
      iOS: DarwinNotificationDetails(),
    ),
    androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
    uiLocalNotificationDateInterpretation:
        UILocalNotificationDateInterpretation.absoluteTime,
    matchDateTimeComponents: DateTimeComponents.time, // repeat daily
  );
}

TZDateTime _nextInstanceOfTime(Time time) {
  final now = tz.TZDateTime.now(tz.local);
  var scheduled = tz.TZDateTime(
    tz.local, now.year, now.month, now.day, time.hour, time.minute,
  );
  if (scheduled.isBefore(now)) {
    scheduled = scheduled.add(const Duration(days: 1));
  }
  return scheduled;
}
Enter fullscreen mode Exit fullscreen mode

Summary

Immediate         → notifications.show()
Scheduled         → notifications.zonedSchedule() + matchDateTimeComponents
Daily repeat      → DateTimeComponents.time
Tap handler       → onDidReceiveNotificationResponse + payload
Enter fullscreen mode Exit fullscreen mode

Local notifications are the lowest-cost way to maintain engagement — no push server required.

Top comments (0)