Skip to content

codeastartup01dev/flutter_awesome_notification

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Flutter Awesome Notification πŸ””

Pub Version License: MIT Platform

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: Display notifications when app is active
  • βœ… Custom Filtering: Flexible callback-based filtering for app-specific logic
  • βœ… 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

πŸš€ Quick Start

Installation

Add to your pubspec.yaml:

dependencies:
  flutter_awesome_notification: ^2.0.1
  firebase_core: ^3.8.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();

  // Step 1: Initialize Firebase FIRST
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  // Step 2: Initialize the notification plugin with Firebase instance
  await FlutterAwesomeNotification.initialize(
    config: FlutterAwesomeNotificationConfig(
      firebaseApp: Firebase.app(), // Pass initialized Firebase instance
      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');
      },
    ),
  );

  runApp(MyApp());
}

That's it! You now have full notification support with just a few lines of code.

⚠️ Important: Always initialize Firebase BEFORE the notification plugin. The plugin validates Firebase initialization and provides helpful error messages if Firebase is not ready.

πŸ“– Configuration

Complete Configuration Example

// Initialize Firebase first
await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform,
);

// Then initialize notification plugin
await FlutterAwesomeNotification.initialize(
  config: FlutterAwesomeNotificationConfig(
    // REQUIRED - Pass initialized Firebase instance
    firebaseApp: Firebase.app(),

    // 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');
    },
    customFilter: (messageData) async {
      // Your app-specific filtering logic
      // Example: Filter notifications based on type and user
      final type = messageData['type'];
      final excludeUserId = messageData['excludeUserId'];
      final currentUserId = getCurrentUserId();
      
      // Don't show user's own action notifications
      if (type == 'action_step_completion' && excludeUserId == currentUserId) {
        return false; // Don't show
      }
      
      // Show all other notifications
      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);
    // },

    // 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_logger and 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)

  1. FCM Message Received β†’ FirebaseMessaging.onMessage stream
  2. Custom Filtering Applied β†’ Action steps, chat rooms, user filtering
  3. Local Notification Shown β†’ Via flutter_local_notifications plugin
  4. Tap Navigation β†’ onNavigate callback with pageName and id

Background (App Minimized)

  1. FCM Message Received β†’ System notification (if notification field present)
  2. No Custom Filtering β†’ Plugin doesn't run in background
  3. User Taps Notification β†’ FirebaseMessaging.onMessageOpenedApp triggers
  4. Navigation on App Open β†’ Same onNavigate callback as foreground

Terminated (App Closed)

  1. FCM Message Received β†’ System notification (if notification field present)
  2. No Custom Filtering β†’ App not running
  3. User Taps Notification β†’ Cold app launch with initial message
  4. 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"
  }
}

Custom Filtering

The plugin provides a flexible filtering system via the customFilter callback:

customFilter: (messageData) async {
  // Implement your app-specific filtering logic here
  // Return true to show notification, false to hide it
  
  // Example: Filter by notification type
  final type = messageData['type'];
  if (type == 'spam') return false;
  
  // Example: Filter by user
  final userId = messageData['userId'];
  if (userId == currentUserId) return false;
  
  // Example: Filter by app state
  final chatRoomId = messageData['chatRoomId'];
  if (isUserInChatRoom(chatRoomId)) return false;
  
  return true; // Show by default
}

πŸ”„ 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:

  1. Check if permissions are granted:
    final enabled = await notificationService.areNotificationsEnabled();
  2. Ensure plugin is initialized before Firebase initialization
  3. Check if custom filters are blocking notifications

Background/Terminated Issues:

  1. Critical: FCM payload must include notification field:
    {
      "notification": {"title": "Title", "body": "Body"}, // REQUIRED
      "data": {"pageName": "route"}
    }
  2. Data-only payloads won't show in background/terminated states
  3. Custom filtering doesn't work in background/terminated

Navigation Not Working

  1. Verify onNavigate callback is set
  2. Ensure pageName is in notification data
  3. 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.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“ž Support & Issues

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages