Search code examples
androidflutterdartmobilenotifications

Is it possible to send a notification while a flutter app is closed?


I am developing an Android app using Flutter and currently working on implementing notifications. I have successfully set up weekly notifications, but I want to add a condition: the notification should be triggered only if the app has not been opened for one week. This should work even when the app is closed.

How can I implement this logic in Flutter?

I've explored options with flutter_local_notifications and background execution, but I'm unsure about the best approach to track the app's last opening time and trigger the notification accordingly.

That is my Code:

import 'package:flutter_local_notifications/flutter_local_notifications.dart';

class NotificationService {
  final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin();

  Future<void> initNotification() async {
    notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.requestNotificationsPermission();
    notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.requestExactAlarmsPermission();
  }

  Future<void> scheduleNotification() async {
    const AndroidNotificationDetails androidNotificationDetails =
    AndroidNotificationDetails(
        'repeating channel id', 'repeating channel name',
        channelDescription: 'repeating description',
        icon: '@drawable/sn_invent');
    const NotificationDetails notificationDetails =
    NotificationDetails(android: androidNotificationDetails);
    await notificationsPlugin.periodicallyShow(0, 'Ziele in Angriff genommen?',
        'Schau doch gerne mal wieder deinen Zielplan an', RepeatInterval.weekly, notificationDetails,
        androidAllowWhileIdle: true);
  }
}

Solution

  • You need to keep track of when the app is opened and when app is closed. You can do this by shared_preferences

    Here's how:

    Future<void> scheduleNotification() async {
        if (await shouldTriggerNotification()) {
          const AndroidNotificationDetails androidNotificationDetails =
              AndroidNotificationDetails(
            'repeating channel id',
            'repeating channel name',
            channelDescription: 'repeating description',
            icon: '@drawable/sn_invent',
          );
          const NotificationDetails notificationDetails =
              NotificationDetails(android: androidNotificationDetails);
          await notificationsPlugin.periodicallyShow(
            0,
            'Ziele in Angriff genommen?',
            'Schau doch gerne mal wieder deinen Zielplan an',
            RepeatInterval.weekly,
            notificationDetails,
            androidAllowWhileIdle: true,
          );
    
          await updateLastOpenedTime();
        }
      }
    
      Future<bool> shouldTriggerNotification() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        DateTime lastOpenedTime =
            DateTime.parse(prefs.getString('lastOpenedTime') ?? '');
    
        int daysDifference = DateTime.now().difference(lastOpenedTime).inDays;
    
        return daysDifference >= 7;
      }
    
      Future<void> updateLastOpenedTime() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        prefs.setString('lastOpenedTime', DateTime.now().toIso8601String());
      }
    }