MaikuB / flutter_local_notifications

A Flutter plugin for displaying local notifications on Android, iOS, macOS and Linux
2.47k stars 1.4k forks source link

Docs mention iOS keeps the 64 notifications that will fire the soonest but it actually keeps the last 64 notifications set regardless of when they will fire #2275

Closed zamanzamzz closed 7 months ago

zamanzamzz commented 8 months ago

This is not behaviour that is officially documented anywhere on Apple Developer docs but it is documented as a community bug report here.

Here is a sample app that reproduces the behaviour on the latest version of this package and the latest stable flutter release (3.19.3). It initializes the plugin and schedules 70 notifications every minute for the next 70 minutes, then gets the pending notifications and prints out the title. You'll see that notifications 7 to 70 is printed out rather than the expected 1 - 64.

First create a flutter project from scratch and do the following commands to add this package and the timezone package:

flutter pub add flutter_local_notifications
flutter pub add timezone

Lastly, replace the contents of main.dart to this and run the app.

// ignore_for_file: avoid_print

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart';
import 'package:timezone/data/latest.dart' as tz;

void main() {
  tz.initializeTimeZones();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
  int _counter = 0;

  @override
  void initState() {
    super.initState();

    flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    flutterLocalNotificationsPlugin
        .initialize(
            const InitializationSettings(iOS: DarwinInitializationSettings()))
        .then((value) async {
      final futures = <Future>[];
      final now = TZDateTime.now(getLocation('America/Vancouver'));
      for (var i = 0; i < 70; i++) {
        futures.add(flutterLocalNotificationsPlugin.zonedSchedule(
          UniqueKey().hashCode,
          '${i + 1}',
          '',
          now.add(Duration(minutes: i + 1)),
          const NotificationDetails(iOS: DarwinNotificationDetails()),
          uiLocalNotificationDateInterpretation:
              UILocalNotificationDateInterpretation.absoluteTime,
        ));
      }
      await Future.wait(futures);
      final pendingNotifications =
          await flutterLocalNotificationsPlugin.pendingNotificationRequests();

      print('pending notifications ------');
      for (final pending in pendingNotifications) {
        print(pending.title);
      }
    });
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}