Flutter: Trigger notifications when app is terminated

137 views Asked by At

Is there a way to implement the following functionality without using a remote server: In my app i can schedule reminders. Those trigger when the app is opened or running in the background but never when it is terminated. Are there any libs that can trigger scheduled notifications when the app is terminated or somehow schedule them to a OS-level of some sort? Or am I required to trigger them by a remote server like firebase?

Currently I am using the flutter_local_notifications package. My NotificationService looks like this:

import 'package:timezone/timezone.dart' as tz;

import '../db_models/reminder_model.dart';

class NotificationService {
  final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

  // Initialize the notification settings
  Future<void> initNotifications() async {
    final InitializationSettings initializationSettings = InitializationSettings(
      android: AndroidInitializationSettings('@mipmap/ic_launcher'),
      iOS: DarwinInitializationSettings(),
      // Add other platform-specific settings if needed
    );

    await _flutterLocalNotificationsPlugin.initialize(
      initializationSettings,
      onDidReceiveNotificationResponse: _onDidReceiveNotificationResponse,
      onDidReceiveBackgroundNotificationResponse: _onDidReceiveBackgroundNotificationResponse,
    );
  }

  // Schedule a notification
  Future<void> scheduleNotification(Reminder reminder) async {
    // Convert triggerTime to a DateTime object
    // Extract the current date
    final currentDate = DateTime.now();
    // Extract the hour and minute from the triggerTime
    final timeParts = reminder.getTriggerTime().split(':');
    final hour = int.parse(timeParts[0]);
    final minute = int.parse(timeParts[1]);

    // Combine them into a DateTime object
    final scheduledTime = DateTime(currentDate.year, currentDate.month, currentDate.day, hour, minute);

    //final DateTime scheduledTime = DateTime.parse(reminder.getTriggerTime());
    final tz.TZDateTime tzScheduledTime = tz.TZDateTime.from(scheduledTime, tz.local);
    print('TriggerTime: $tzScheduledTime');


    // Define the notification details
    var androidDetails = AndroidNotificationDetails(
      'channel_id',
      'channel_name',
      channelDescription: 'channel_description',
      importance: Importance.max,
      priority: Priority.high,
    );
    var iosDetails = DarwinNotificationDetails();
    var platformDetails = NotificationDetails(android: androidDetails, iOS: iosDetails);

    // Schedule the notification
    await _flutterLocalNotificationsPlugin.zonedSchedule(
      reminder.getId(),
      'Water Reminder',
      'Time to drink water!',
      tzScheduledTime,
      platformDetails,
      androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
      uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
      matchDateTimeComponents: DateTimeComponents.time, // To repeat daily at the same time
      payload: "hey boss!!!!"
    );
    var pendingNotifications = await _flutterLocalNotificationsPlugin.pendingNotificationRequests();

    for (var notification in pendingNotifications) {
      print('Notification: id=${notification.id}, title=${notification.title}, body=${notification.body}, payload=${notification.payload}');
    }
  }

  Future<void> triggerNotificationNow(int notificationId) async {
    // Retrieve the details of the scheduled notification by its ID
    // This step depends on how you store your scheduled notifications

    var androidDetails = AndroidNotificationDetails(
      'channel_id',
      'channel_name',
      channelDescription: 'channel_description',
      importance: Importance.max,
      priority: Priority.high,
    );
    var iosDetails = DarwinNotificationDetails();
    var platformDetails = NotificationDetails(android: androidDetails, iOS: iosDetails);


    // Schedule the notification to trigger immediately
    await _flutterLocalNotificationsPlugin.zonedSchedule(
    notificationId,
    "Test",
    "Wabec lol haha",
    tz.TZDateTime.now(tz.local).add(Duration(seconds: 5)),
platformDetails, uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime
    );
    }

  // Handle notification response when the app is running
  void _onDidReceiveNotificationResponse(NotificationResponse response) {
    // Handle the notification response
  }

  // Handle notification response when the app is in the background
}

void _onDidReceiveBackgroundNotificationResponse(
    NotificationResponse response) {
  print("Notification clicked with payload: ${response.payload}");
  // Handle the background notification response
}

When I schedule a notification, it is triggered when the app is running in the foreground/background but never when it is terminated.

I tested this on the Android APIs: 28, 29 and 34 (And I am aware that from a certain API onward you need special permissions for exact scheduling)

1

There are 1 answers

0
Yakup Okumuş On

You need to use Firebase push notifications or One Signal because ios dooes'nt support background fetch or that kind of thing. After that you can redirect coming notifications (from that services) your local solutions.