Harsh Patwari
 · Founder | CEO

Scheduling local notifications with flutter_local_notifications

Custom Code

I am trying to schedule a weekly notification for a given list of weekdays and time.
Here is the code -


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;

Future<void> scheduleWeeklyNotification(
  int id,
  FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin,
  NotificationDetails platformChannelSpecifics,
  DateTime notificationTime,
  List<int> weekdays,
) async {
  for (int weekday in weekdays) {
    await flutterLocalNotificationsPlugin.zonedSchedule(
      int.parse('$id$weekday'),
      'Title',
      'Body',
      _nextInstanceOfWeekdayAndTime(weekday, notificationTime),
      platformChannelSpecifics,
      androidAllowWhileIdle: true,
      androidScheduleMode: AndroidScheduleMode.alarmClock,
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.wallClockTime,
      payload: 'notification:$id',
      matchDateTimeComponents: DateTimeComponents.dayOfWeekAndTime,
    );
  }
}

tz.TZDateTime _nextInstanceOfWeekdayAndTime(
    int weekday, DateTime notificationTime) {
  tz.initializeTimeZones();
  tz.TZDateTime now = tz.TZDateTime.now(tz.local);
  tz.TZDateTime scheduledDate = tz.TZDateTime(
    tz.local,
    now.year,
    now.month,
    now.day,
    notificationTime.hour,
    notificationTime.minute,
    0,
  );

  while (scheduledDate.weekday % 7 != weekday) {
    scheduledDate = scheduledDate.add(const Duration(days: 1));
  }

  if (scheduledDate.isBefore(now)) {
    scheduledDate = scheduledDate.add(const Duration(days: 7));
  }

  return scheduledDate;
}

Future scheduleNudge(
  int id,
  DateTime notificationTime,
  List<int> weekdays,
  Future Function(String? payload)? handleNotificationResponse,
) async {
  FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();

  const AndroidInitializationSettings initializationSettingsAndroid =
      AndroidInitializationSettings('@mipmap/ic_launcher');

  final DarwinInitializationSettings initializationSettingsDarwin =
      DarwinInitializationSettings(
    requestAlertPermission: true,
    requestBadgePermission: true,
    requestSoundPermission: true,
  );

  final InitializationSettings initializationSettings = InitializationSettings(
    android: initializationSettingsAndroid,
    iOS: initializationSettingsDarwin,
  );

  flutterLocalNotificationsPlugin.initialize(
    initializationSettings,
    onDidReceiveNotificationResponse: (response) {
      handleNotificationResponse!(response.payload);
    },
  );

  const AndroidNotificationDetails androidPlatformChannelSpecifics =
      AndroidNotificationDetails(
    'weekly_notification_id',
    'Weekly Notification',
    channelDescription: 'Weekly Notifications',
    importance: Importance.max,
    priority: Priority.high,
  );
  const DarwinNotificationDetails iosPlatformChannelSpecifics =
      DarwinNotificationDetails(
    threadIdentifier: 'Notification',
  );
  const NotificationDetails platformChannelSpecifics = NotificationDetails(
      android: androidPlatformChannelSpecifics,
      iOS: iosPlatformChannelSpecifics);

  // Set the schedule and enable notifications
  await scheduleWeeklyNotification(
    id,
    flutterLocalNotificationsPlugin,
    platformChannelSpecifics,
    notificationTime,
    weekdays,
  );

  final List<PendingNotificationRequest> activeNotifications =
      await flutterLocalNotificationsPlugin.pendingNotificationRequests();
  assert(activeNotifications.isNotEmpty);
}

The assertion is always passing but I do not receive the notifications.

This is the logic to request permissions which is working fine -

Future requestNotificationsPermission() async {
  if (Platform.isAndroid) {
    final androidInfo = await DeviceInfoPlugin().androidInfo;
    if (androidInfo.version.sdkInt >= 31) {
      // Request scheduleExactAlarm permission for Android 12 and above
      await Permission.scheduleExactAlarm
          .onPermanentlyDeniedCallback(() {
            openAppSettings();
          })
          .request()
          .isGranted;
    }
  }

  // Request notification permission
  await Permission.notification
      .onPermanentlyDeniedCallback(() {
        openAppSettings();
      })
      .request()
      .isGranted;
}


I have also added SCHEDULE_EXACT_ALARM and RECEIVE_BOOT_COMPLETED custom permissions.

Are there any other changes that I need to make in AndroidManifest.xml to get this to work?

What have you tried so far?
Did you check FlutterFlow's Documentation for this topic?
Yes
8 replies