flutter_awesome_notification 1.0.0
flutter_awesome_notification: ^1.0.0 copied to clipboard
A comprehensive notification plugin for Flutter with FCM, local notifications, and intelligent filtering.
Flutter Awesome Notification đ #
A comprehensive, production-ready notification plugin for Flutter apps with Firebase Cloud Messaging (FCM) and local notifications. Handles foreground notifications with intelligent filtering and seamless navigation across all app states.
⨠Features #
- â Foreground Notification Handling: Intelligent filtering and display when app is active
- â Intelligent Filtering: Action step, chat room, and custom notification filtering
- â Navigation Integration: Seamless navigation across all app states (foreground/background/terminated)
- â Topic Subscriptions: Easy FCM topic management
- â Local Notifications: Immediate and scheduled local notifications
- â Highly Configurable: Builder pattern with sensible defaults
- â Minimal Code: Easy setup with very little boilerplate
- â FCM Token Management: Automatic token handling and refresh
- â Custom Logging: Integrate with your preferred logging solution
- â Type-Safe: Full type safety with comprehensive configuration
đĻ Repository #
- Repository: GitHub
- Pub.dev: Package
- Issues: GitHub Issues
- Changelog: CHANGELOG.md
đ Quick Start #
Installation #
Add to your pubspec.yaml:
dependencies:
flutter_awesome_notification: ^1.0.0
Basic Setup #
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_awesome_notification/flutter_awesome_notification.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize the notification plugin BEFORE Firebase
await FlutterAwesomeNotification.initialize(
config: FlutterAwesomeNotificationConfig(
firebaseOptions: DefaultFirebaseOptions.currentPlatform,
mainChannelId: 'my_app_notifications',
mainChannelName: 'My App Notifications',
onNotificationTap: (data) {
print('Notification tapped: $data');
},
onNavigate: (pageName, id, data) {
print('Navigate to: $pageName with id: $id');
},
),
);
// Initialize Firebase
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
That's it! You now have full notification support with just a few lines of code.
đ Configuration #
Complete Configuration Example #
await FlutterAwesomeNotification.initialize(
config: FlutterAwesomeNotificationConfig(
// REQUIRED
firebaseOptions: DefaultFirebaseOptions.currentPlatform,
// Channel Configuration
mainChannelId: 'my_app_channel',
mainChannelName: 'My App Notifications',
mainChannelDescription: 'General notifications',
notificationIcon: '@mipmap/ic_launcher',
// Callbacks
onNotificationTap: (data) {
// Handle notification tap
print('Tapped: $data');
},
onNavigate: (pageName, id, data) {
// Custom navigation
// Example: GoRouter.of(context).push('/$pageName/$id');
},
getCurrentUserId: () {
// Return current user ID for filtering
return userCubit.getUserModel()?.id;
},
customFilter: (messageData) async {
// Custom filtering logic
// Return true to show, false to hide
return true;
},
// Logging Options
// Option 1: External logger (recommended - unified logging)
// Compatible with flutter_awesome_logger and other logging solutions
externalLogger: logger, // Your logger instance with d(), i(), w(), e() methods
// Option 2: Logger callback (legacy support)
// logger: (message, {error}) {
// myLogger.log(message, error: error);
// },
// Filtering Options
enableActionStepFiltering: true,
enableChatRoomFiltering: true,
isActiveChatRoom: (chatRoomId) {
// Check if user is currently in this chat room
return appCubit.isActiveChatRoom(chatRoomId);
},
chatPageRoute: 'chat-page',
// Notification Types
notificationTypeToPage: {
'action_step': 'challenge-details',
'chat_message': 'chat-room',
'event_reminder': 'event-details',
},
// Advanced
enableLogging: true,
requestPermissionOnInit: true,
showAlertInForeground: true,
showBadgeInForeground: true,
playSoundInForeground: true,
defaultNotificationTitle: 'New Update',
defaultNotificationBody: 'You have a new update',
environment: 'production',
),
);
Minimal Configuration #
For a basic setup, only Firebase options are required:
await FlutterAwesomeNotification.initialize(
config: FlutterAwesomeNotificationConfig(
firebaseOptions: DefaultFirebaseOptions.currentPlatform,
),
);
đ¯ Usage #
Access the Service #
final notificationService = FlutterAwesomeNotification.instance;
Topic Subscriptions #
// Subscribe to a topic
await notificationService.subscribeToTopic('announcements');
// Unsubscribe from a topic
await notificationService.unsubscribeFromTopic('announcements');
Get FCM Token #
final token = await notificationService.getDeviceToken();
print('FCM Token: $token');
Show Local Notification #
await notificationService.showLocalNotification(
id: 123,
title: 'Hello!',
body: 'This is a local notification',
data: {'key': 'value'},
);
Schedule Notification #
await notificationService.scheduleNotification(
id: 124,
title: 'Reminder',
body: 'Don\'t forget to check this!',
scheduledDate: DateTime.now().add(Duration(hours: 2)),
data: {'reminder_type': 'task'},
);
Cancel Notifications #
// Cancel specific notification
await notificationService.cancelNotification(123);
// Cancel all notifications
await notificationService.cancelAllNotifications();
Check Notification Permissions #
final enabled = await notificationService.areNotificationsEnabled();
if (!enabled) {
await notificationService.requestPermissions();
}
Unified Logging with External Logger #
The plugin supports external logger instances for unified logging across your app:
// 1. Create or use your existing logger instance
class MyLogger {
void d(String message) => print('đ DEBUG: $message');
void i(String message) => print('âšī¸ INFO: $message');
void w(String message) => print('â ī¸ WARNING: $message');
void e(String message, {dynamic error, StackTrace? stackTrace}) {
print('â ERROR: $message');
if (error != null) print('Error: $error');
}
}
final logger = MyLogger();
// 2. Pass it to the plugin during initialization
await FlutterAwesomeNotification.initialize(
config: FlutterAwesomeNotificationConfig(
firebaseOptions: DefaultFirebaseOptions.currentPlatform,
enableLogging: true,
externalLogger: logger, // đ¯ Your logger instance
),
);
Benefits:
- â Unified logging across all plugins (deeplink, notification, etc.)
- â
Compatible with
flutter_awesome_loggerand other logging solutions - â Consistent log format and filtering
- â No need for custom callbacks
Supported Log Levels:
d()- Debug messages (initialization, state changes)i()- Info messages (successful operations)w()- Warning messages (non-critical issues)e()- Error messages (failures, exceptions)
đ How It Works #
App State Behavior #
Foreground (App Open & Visible)
- FCM Message Received â
FirebaseMessaging.onMessagestream - Custom Filtering Applied â Action steps, chat rooms, user filtering
- Local Notification Shown â Via
flutter_local_notificationsplugin - Tap Navigation â
onNavigatecallback withpageNameandid
Background (App Minimized)
- FCM Message Received â System notification (if
notificationfield present) - No Custom Filtering â Plugin doesn't run in background
- User Taps Notification â
FirebaseMessaging.onMessageOpenedApptriggers - Navigation on App Open â Same
onNavigatecallback as foreground
Terminated (App Closed)
- FCM Message Received â System notification (if
notificationfield present) - No Custom Filtering â App not running
- User Taps Notification â Cold app launch with initial message
- Navigation on Launch â
FirebaseMessaging.getInitialMessage()âonNavigate
Key Differences by App State #
| Feature | Foreground | Background | Terminated |
|---|---|---|---|
| Custom Filtering | â Full | â None | â None |
| Notification Display | â Plugin | â System | â System |
| Navigation | â Immediate | â On tap | â On launch |
| Plugin Processing | â Active | â Dormant | â Dormant |
FCM Payload Requirements #
For Background/Terminated delivery:
{
"notification": {
"title": "New Message",
"body": "You have a new message"
},
"data": {
"pageName": "chat-room",
"id": "room123",
"type": "message"
}
}
â ī¸ Data-only payloads won't show in background/terminated:
// â Won't show in background/terminated
{
"data": {
"pageName": "chat-room",
"id": "room123"
}
}
Filtering System #
The plugin provides multiple layers of filtering:
- Action Step Filtering: Prevents users from seeing their own action notifications
- Chat Room Filtering: Hides notifications when user is in the chat room
- Custom Filtering: Your own logic via callback
- Type Filtering: Filter by notification type
đ Migration Guide #
From Manual FCM Setup #
If you're currently handling FCM manually, migration is straightforward:
// Before (Manual Setup)
FirebaseMessaging.onMessage.listen((message) {
// Custom filtering logic
// Manual notification display
// Navigation handling
});
FirebaseMessaging.onMessageOpenedApp.listen((message) {
// Navigation from background tap
});
FirebaseMessaging.getInitialMessage().then((message) {
// Navigation from terminated state
});
// After (Plugin)
await FlutterAwesomeNotification.initialize(
config: FlutterAwesomeNotificationConfig(
firebaseOptions: DefaultFirebaseOptions.currentPlatform,
onNavigate: (pageName, id, data) {
// Your navigation logic here
// Works for all app states automatically
},
),
);
// That's it! Plugin handles everything else
đą Server-Side Configuration #
FCM Message Format #
For proper filtering, send data-only messages:
{
"data": {
"type": "action_step_completion",
"excludeUserId": "user123",
"challengeId": "challenge456",
"pageName": "challenge-details",
"id": "challenge456",
"title": "Challenge Update",
"body": "Someone completed a step!"
},
"token": "fcm_device_token"
}
đ Troubleshooting #
Notifications Not Showing #
Foreground Issues:
- Check if permissions are granted:
final enabled = await notificationService.areNotificationsEnabled(); - Ensure plugin is initialized before Firebase initialization
- Check if custom filters are blocking notifications
Background/Terminated Issues:
- Critical: FCM payload must include
notificationfield:{ "notification": {"title": "Title", "body": "Body"}, // REQUIRED "data": {"pageName": "route"} } - Data-only payloads won't show in background/terminated states
- Custom filtering doesn't work in background/terminated
Navigation Not Working #
- Verify
onNavigatecallback is set - Ensure
pageNameis in notification data - Check navigation implementation in callback
đ Comparison #
| Feature | flutter_awesome_notification | Manual Setup |
|---|---|---|
| Setup Complexity | âī¸ Simple | âī¸âī¸âī¸âī¸ Complex |
| Lines of Code | ~10 lines | ~500+ lines |
| Filtering System | â Built-in | â Manual |
| Topic Management | â Built-in | â Manual |
| Documentation | â Complete | â Variable |
| Maintenance | â Plugin updates | â Manual updates |
đ License #
MIT License - see LICENSE file for details
đ¤ Contributing #
We welcome contributions! Please feel free to submit issues, feature requests, or pull requests.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
đ Support & Issues #
- đ Documentation: GitHub README
- đ Bug Reports: GitHub Issues
- đĄ Feature Requests: GitHub Issues
- đ§ General Questions: Use GitHub Discussions