Flutter Notification Manager
A comprehensive Flutter notification manager package that provides unified local and remote notification support across all platforms.
Features
π Core Features
- Unified Interface: Single API for both Firebase Cloud Messaging (FCM) and local notifications
- Cross-Platform Support: Works seamlessly on Android, iOS, Web, Windows, macOS, and Linux
- Template System: Pre-built notification templates for common use cases
- Advanced Scheduling: Timezone-aware scheduling with recurring notifications
- User Preferences: Comprehensive user preference management with quiet hours
- Permission Management: Streamlined permission handling across platforms
- Rich Media: Support for images, actions, and interactive notifications
- Delivery Tracking: Monitor notification delivery status and history (Firebase only)
- Type Safety: Full type safety throughout the implementation
π± Notification Types
- Basic Notifications: Simple title and body notifications
- Rich Media: Notifications with images and custom styling
- Interactive: Notifications with action buttons and user input
- Message: Chat-style notifications with reply actions
- Reminder: Task and appointment reminders with snooze
- Promotional: Marketing notifications with call-to-action
- Progress: Download and task progress notifications
- Critical Alerts: High-priority system alerts
- Grouped: Conversation and category-based grouping
π§ Advanced Features
- Firebase Integration: Complete FCM support with token management
- Local Scheduling: Advanced local notification scheduling with timezone support
- Quiet Hours: Automatic notification scheduling around user preferences
- Channel Management: Create and manage notification channels (Android)
- Background Processing: Handle notifications when app is backgrounded
- Fallback Strategies: Automatic fallback from Firebase to local notifications
- Permission Debugging: Comprehensive permission status checking and debugging
- Accessibility: Screen reader and accessibility features
Installation
Add this package to your pubspec.yaml:
dependencies:
  notification_manager: ^x.y.z
  firebase_core: ^z.y.z
  firebase_messaging: ^z.y.z
  flutter_local_notifications: ^z.y.z
  timezone: ^z.y.z
Run:
flutter pub get
Setup
1. Firebase Setup (for Push Notifications)
Android Setup
- Follow the Firebase setup guide
- Add google-services.jsontoandroid/app/
- Update android/app/build.gradle:
android {
    compileSdkVersion 34
    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 34
    }
}
- Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<application>
    <!-- Firebase Messaging Service -->
    <service
        android:name="io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    <!-- Notification click handler -->
    <receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
    <receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
            <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
            <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
        </intent-filter>
    </receiver>
</application>
iOS Setup
- Add GoogleService-Info.plisttoios/Runner/
- Update ios/Runner/Info.plist:
<key>UIBackgroundModes</key>
<array>
    <string>remote-notification</string>
    <string>background-fetch</string>
</array>
- Enable push notifications in Xcode project capabilities
2. Local Notifications Setup
Android
Add notification icons to android/app/src/main/res/drawable/:
- app_icon.png(default notification icon)
- notification_icon.png(monochrome icon for Android 5.0+)
iOS
No additional setup required for local notifications.
3. Initialize in Your App
import 'package:firebase_core/firebase_core.dart';
import 'package:notification_manager/notification_manager.dart';
import 'package:timezone/data/latest.dart' as tz;
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initialize timezone data
  tz.initializeTimeZones();
  // Initialize Firebase
  await Firebase.initializeApp();
  runApp(MyApp());
}
Usage
Basic Setup
import 'package:notification_manager/notification_manager.dart';
class NotificationService {
  late final ComprehensiveNotificationManager _notificationManager;
  Future<void> initialize() async {
    _notificationManager = await ComprehensiveNotificationManager.getInstance();
    // Initialize with user preferences
    final userPreferences = UserPreferencesModel(
      globalNotificationsEnabled: true,
      soundEnabled: true,
      vibrationEnabled: true,
      quietHours: QuietHoursSettings(
        enabled: true,
        startTime: '22:00',
        endTime: '08:00',
      ),
    );
    final error = await _notificationManager.initialize(
      userPreferences: userPreferences,
    );
    if (error != null) {
      print('Failed to initialize: ${error.message}');
    }
    // Listen to notification events
    _notificationManager.onNotificationReceived.listen((payload) {
      print('Received: ${payload.title}');
    });
    _notificationManager.onNotificationOpened.listen((payload) {
      print('Opened: ${payload.title}');
      // Handle navigation based on payload
    });
    _notificationManager.onNotificationAction.listen((actionData) {
      print('Action: ${actionData['actionId']}');
      // Handle notification actions
    });
  }
}
Request Permissions
Future<void> requestPermissions() async {
  final (error, status) = await _notificationManager.requestAllPermissions();
  if (error == null && status == PermissionStatus.granted) {
    print('All permissions granted');
  } else {
    print('Permissions status: $status, Error: ${error?.message}');
  }
}
Show Basic Notification
Future<void> showBasicNotification() async {
  final payload = _notificationManager.templates.createBasicNotification(
    id: 'basic_${DateTime.now().millisecondsSinceEpoch}',
    title: 'Hello!',
    body: 'This is a basic notification',
  );
  final error = await _notificationManager.showNotification(payload);
  if (error != null) {
    print('Failed to show notification: ${error.message}');
  }
}
Show Rich Media Notification
Future<void> showRichNotification() async {
  final payload = _notificationManager.templates.createRichMediaNotification(
    id: 'rich_${DateTime.now().millisecondsSinceEpoch}',
    title: 'New Photo',
    body: 'Check out this amazing photo!',
    imageUrl: 'https://example.com/photo.jpg',
    bigPicture: 'https://example.com/big_photo.jpg',
  );
  await _notificationManager.showNotification(payload);
}
Interactive Notifications
Future<void> showInteractiveNotification() async {
  final actions = _notificationManager.templates.createCommonActions(
    includeReply: true,
    includeMarkAsRead: true,
    includeView: true,
  );
  final payload = _notificationManager.templates.createInteractiveNotification(
    id: 'interactive_${DateTime.now().millisecondsSinceEpoch}',
    title: 'New Message',
    body: 'You have received a new message',
    actions: actions,
  );
  await _notificationManager.showNotification(payload);
}
Schedule Notifications
Future<void> scheduleNotification() async {
  final payload = _notificationManager.templates.createReminderNotification(
    id: 'reminder_${DateTime.now().millisecondsSinceEpoch}',
    title: 'Meeting Reminder',
    body: 'Team meeting in 15 minutes',
  );
  final scheduledTime = DateTime.now().add(Duration(minutes: 15));
  final error = await _notificationManager.scheduleNotification(
    payload,
    scheduledTime,
  );
  if (error == null) {
    print('Notification scheduled successfully');
  }
}
Recurring Notifications
Future<void> scheduleRecurringNotification() async {
  final payload = _notificationManager.templates.createReminderNotification(
    id: 'daily_reminder',
    title: 'Daily Reminder',
    body: 'Don\'t forget to take your medication',
  );
  final firstTime = DateTime.now().add(Duration(hours: 1));
  await _notificationManager.scheduleRecurringNotification(
    payload,
    firstTime,
    RepeatInterval.daily,
    endDate: DateTime.now().add(Duration(days: 30)),
  );
}
Message Notifications
Future<void> showMessageNotification() async {
  final payload = _notificationManager.templates.createMessageNotification(
    id: 'message_${DateTime.now().millisecondsSinceEpoch}',
    senderName: 'John Doe',
    message: 'Hey, how are you doing?',
    senderAvatar: 'https://example.com/avatar.jpg',
    conversationId: 'conversation_123',
  );
  await _notificationManager.showNotification(payload);
}
User Preferences Management
Future<void> updateUserPreferences() async {
  final preferences = UserPreferencesModel(
    globalNotificationsEnabled: true,
    soundEnabled: false, // Disable sounds
    vibrationEnabled: true,
    quietHours: QuietHoursSettings(
      enabled: true,
      startTime: '22:00',
      endTime: '07:00',
      weekdaysOnly: true,
    ),
    blockedSenders: ['spam_sender_id'],
  );
  final error = await _notificationManager.updateUserPreferences(preferences);
  if (error == null) {
    print('Preferences updated successfully');
  }
}
Create Notification Channels
Future<void> createNotificationChannel() async {
  final error = await _notificationManager.createNotificationChannel(
    channelId: 'important_updates',
    channelName: 'Important Updates',
    channelDescription: 'Critical app updates and announcements',
    importance: NotificationImportance.high,
    enableVibration: true,
    enableLights: true,
  );
  if (error == null) {
    print('Channel created successfully');
  }
}
Advanced Features
Custom Templates
class CustomNotificationTemplates {
  static NotificationPayload createOrderUpdateNotification({
    required String orderId,
    required String status,
    required String estimatedTime,
  }) {
    return NotificationPayload(
      id: 'order_$orderId',
      title: 'Order Update',
      body: 'Your order #$orderId is $status. ETA: $estimatedTime',
      data: {
        'type': 'order_update',
        'orderId': orderId,
        'status': status,
      },
      importance: NotificationImportance.high,
      category: 'order',
      actions: [
        NotificationAction(
          id: 'track_order',
          title: 'Track Order',
          showsUserInterface: true,
        ),
        NotificationAction(
          id: 'contact_support',
          title: 'Contact Support',
          showsUserInterface: true,
        ),
      ],
    );
  }
}
Handle Notification Actions
void handleNotificationActions() {
  _notificationManager.onNotificationAction.listen((actionData) {
    final actionId = actionData['actionId'];
    final notificationId = actionData['notificationId'];
    switch (actionId) {
      case 'reply':
        final replyText = actionData['input'];
        handleReply(notificationId, replyText);
        break;
      case 'mark_read':
        markAsRead(notificationId);
        break;
      case 'snooze':
        snoozeNotification(notificationId);
        break;
    }
  });
}
Permission Debugging
Future<void> debugPermissions() async {
  final (error, status) = await _notificationManager.checkPermissionStatus();
  if (error == null) {
    print('Permission status: $status');
    // Check specific permissions
    final (_, enabled) = await _notificationManager.areNotificationsEnabled();
    print('Notifications enabled: $enabled');
  } else {
    print('Permission check failed: ${error.message}');
  }
}
Platform-Specific Considerations
Android
- Notification Channels: Required for Android 8.0+, automatically created by the package
- Battery Optimization: Handle Doze mode and app standby
- Exact Alarms: Required for precise scheduling on Android 12+
- Custom Sounds: Place sound files in android/app/src/main/res/raw/
iOS
- Provisional Authorization: Allow quiet notifications without explicit permission
- Critical Alerts: Bypass Do Not Disturb (requires special entitlement)
- Notification Service Extension: For rich media and modification
- Background App Refresh: Required for background notification processing
Web
- Firebase Only: Web platform only supports Firebase notifications
- Service Worker: Required for background notification handling
- HTTPS: Required for web push notifications
Desktop (Windows, macOS, Linux)
- Local Only: Desktop platforms use local notifications only
- System Integration: Native system notification integration
- Focus Assist: Respect system Do Not Disturb settings
Testing
Local Testing
void main() {
  group('Notification Manager Tests', () {
    late ComprehensiveNotificationManager notificationManager;
    setUp(() async {
      notificationManager = await ComprehensiveNotificationManager.getInstance();
    });
    tearDown(() async {
      await notificationManager.dispose();
    });
    testWidgets('should initialize successfully', (tester) async {
      final error = await notificationManager.initialize();
      expect(error, isNull);
      expect(notificationManager.isInitialized, isTrue);
    });
    testWidgets('should show basic notification', (tester) async {
      await notificationManager.initialize();
      final payload = notificationManager.templates.createBasicNotification(
        id: 'test_notification',
        title: 'Test',
        body: 'Test notification',
      );
      final error = await notificationManager.showNotification(payload);
      expect(error, isNull);
    });
  });
}
Firebase Testing
Use Firebase Console's "Cloud Messaging" section to send test notifications to your app.
Troubleshooting
Common Issues
- 
Notifications not showing on Android - Check notification permissions using checkPermissionStatus()
- Verify notification channels are created
- Ensure app is not in battery optimization whitelist
 
- Check notification permissions using 
- 
Firebase notifications not received - Verify Firebase project setup and google-services.json
- Check internet connectivity
- Ensure Firebase token is properly registered
 
- Verify Firebase project setup and 
- 
iOS notifications not working - Verify push notification capability is enabled in Xcode
- Check GoogleService-Info.plistplacement
- Ensure proper provisioning profile
 
- 
Scheduled notifications not firing - Verify timezone configuration with initializeTimeZones()
- Check exact alarm permissions on Android 12+
- Ensure app has proper background permissions
 
- Verify timezone configuration with 
Debug Mode
The package automatically enables debug logging when Flutter is in debug mode. Look for logs prefixed with notification-related information.
API Reference
Main Classes
- ComprehensiveNotificationManager: Main manager class
- NotificationPayload: Notification data structure
- NotificationTemplateBuilder: Pre-built notification templates
- UserPreferencesModel: User preference management
- NotificationFailure: Error handling
Key Enums
- NotificationImportance: Notification priority levels
- NotificationPriority: Platform-specific priority
- PermissionStatus: Permission states
- RepeatInterval: Recurring notification intervals
Contributing
- Fork the repository on GitHub
- Create a feature branch (git checkout -b feature/amazing-feature)
- Add tests for new features
- Ensure all tests pass (flutter test)
- Commit your changes (git commit -m 'Add amazing feature')
- Push to the branch (git push origin feature/amazing-feature)
- Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
- π Issues: GitHub Issues
- π Documentation: API Reference
- π¬ Discussions: GitHub Discussions
Changelog
See CHANGELOG.md for version history and updates.
Acknowledgments
- Built with flutter_local_notifications
- Firebase integration using firebase_messaging
- Utilities from flutter_shared_utilities
Libraries
- core/constants/notification_enums
- core/errors/notification_failure
- core/helpers/foreground_notification_manager
- core/helpers/notification_permission_manager
- core/helpers/notification_scheduler_debugger
- core/helpers/notification_template_builder
- core/services/comprehensive_notification_manager
- core/utils/notification_scheduler
- features/notifications/data/models/notification_action
- features/notifications/data/models/notification_action_input
- features/notifications/data/models/notification_payload
- features/notifications/data/models/user_preferences_model
- features/notifications/data/repositories/firebase_notification_repository
- features/notifications/data/repositories/local_notification_repository
- features/notifications/data/repositories/unified_notification_repository
- features/notifications/domain/entities/delivery_status_entity
- features/notifications/domain/entities/notification_entity
- features/notifications/domain/entities/notification_settings_entity
- features/notifications/domain/repositories/notification_repository
- features/notifications/presentation/widgets/foreground_notification_widget
- notification_manager
- A comprehensive Flutter notification manager package that provides local and remote notification support.