notification_manager 1.0.1
notification_manager: ^1.0.1 copied to clipboard
A comprehensive Flutter notification manager package that provides local and remote notification support.
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.json
toandroid/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.plist
toios/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.plist
placement - 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 classNotificationPayload
: Notification data structureNotificationTemplateBuilder
: Pre-built notification templatesUserPreferencesModel
: User preference managementNotificationFailure
: Error handling
Key Enums #
NotificationImportance
: Notification priority levelsNotificationPriority
: Platform-specific priorityPermissionStatus
: Permission statesRepeatInterval
: 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