firebase_easy_notify 1.0.2
firebase_easy_notify: ^1.0.2 copied to clipboard
The easiest way to handle Firebase Cloud Messaging + Local Notifications + Timezone-aware scheduling in Flutter (Android & iOS)
π Firebase Easy Notify #
The easiest way to handle Firebase Cloud Messaging + Local Notifications + Timezone-aware scheduling in Flutter
Set up fully working notifications (FCM push + local scheduled reminders) for both Android and iOS with just 3-5 lines of code.
β¨ Features #
- π Super Simple API - Just call
EasyNotify.init()and you're ready - π± FCM Integration - Firebase Cloud Messaging with automatic foreground handling
- β° Smart Scheduling - Timezone-aware weekly/batch/one-time notifications
- π Timezone Support - Automatically handles user's local timezone
- π’ Topic Management - Easy subscribe/unsubscribe with user type helpers
- π― Batch Scheduling - Schedule multiple notifications at once
- π Tap Handling - Built-in callbacks for notification interactions
- π Debug Friendly - Comprehensive logging with
[EasyNotify]prefix - π¨ Production Ready - Clean architecture, error handling, and best practices
π¦ Installation #
Add to your pubspec.yaml:
dependencies:
firebase_easy_notify: ^1.0.0
firebase_core: ^2.24.2 # Required for Firebase initialization
That's it! Firebase Easy Notify exports all the types you need (RemoteMessage, NotificationResponse, etc.) so you don't need to add firebase_messaging or flutter_local_notifications separately.
Run:
flutter pub get
Note: If you previously had
firebase_messagingorflutter_local_notificationsin your dependencies, you can safely remove them. EasyNotify manages these internally and exports the necessary types.
π Quick Start #
1. Initialize (in main.dart) #
import 'package:firebase_core/firebase_core.dart';
import 'package:easy_notify/easy_notify.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Firebase
await Firebase.initializeApp();
// Initialize EasyNotify
await EasyNotify.init(
androidIcon: '@mipmap/ic_launcher',
requestPermissionOnInit: true,
onNotificationTap: (response) {
print('Notification tapped: ${response.payload}');
},
onMessageOpened: (message) {
print('FCM message opened: ${message.data}');
},
);
runApp(MyApp());
}
2. Show Immediate Notification #
EasyNotify.show(
title: 'Hello!',
body: 'This is a test notification',
payload: 'some_data',
);
3. Schedule Weekly Notification #
EasyNotify.scheduleWeekly(
id: 1,
day: DateTime.monday,
hour: 22,
minute: 0,
title: 'Workout Time!',
body: 'Let\'s keep the streak πͺ',
);
4. Schedule Batch Notifications #
Perfect for scheduling notifications on multiple days at multiple times:
EasyNotify.scheduleBatch([
ScheduleModel(
days: [DateTime.monday, DateTime.wednesday, DateTime.friday],
times: [
TimeOfDay(hour: 10, minute: 0),
TimeOfDay(hour: 18, minute: 0),
],
title: 'Reminder',
body: 'Time to check in!',
),
]);
5. Topic Management #
// Subscribe to topics
EasyNotify.subscribe('all_users');
EasyNotify.subscribeMultiple(['sports', 'offers']);
// Unsubscribe
EasyNotify.unsubscribe('premium_users');
// User type helper (automatically manages premium/free topics)
EasyNotify.setUserType(UserType.premium);
6. Get FCM Token #
String? token = await EasyNotify.getToken();
print('FCM Token: $token');
7. Listen to Events #
// Foreground messages
EasyNotify.onMessage.listen((message) {
print('Received: ${message.notification?.title}');
});
// Notification taps
EasyNotify.onTap.listen((response) {
print('Tapped: ${response.payload}');
});
// FCM notification opened
EasyNotify.onMessageOpened.listen((message) {
print('Opened: ${message.data}');
});
π Timezone Handling #
EasyNotify automatically handles timezones so your notifications show at the correct local time for each user.
How it works: #
- Device Timezone Detection: Automatically detects the user's timezone using
flutter_timezone - Timezone Database: Initializes the full timezone database with
timezonepackage - Smart Scheduling: All scheduled notifications use
zonedSchedulewith the user's local timezone
Example Scenario: #
You schedule a notification for 10:00 PM using EasyNotify.scheduleWeekly():
EasyNotify.scheduleWeekly(
id: 1,
day: DateTime.monday,
hour: 22, // 10:00 PM
minute: 0,
title: 'Evening Reminder',
body: 'Time to check in!',
);
Result:
- π¬π§ UK user sees it at 10:00 PM GMT (their local time)
- π΅π° Pakistan user sees it at 10:00 PM PKT (their local time)
- πΊπΈ USA user sees it at 10:00 PM EST (their local time)
Each user receives the notification at 10 PM in their own timezone!
Firebase Console Scheduled Campaigns: #
When using Firebase Console to schedule campaigns:
- Important: Select "Recipient's local time zone" option when scheduling
- EasyNotify ensures the device timezone is correctly initialized
- Firebase uses this timezone information to deliver at the correct local time
Firebase Console Steps:
- Go to Firebase Console β Cloud Messaging β New Campaign
- Compose your notification
- Under "Scheduling", select "Recipient's local time zone" β
- Set your desired time (e.g., 10:00 PM)
- All users receive it at 10:00 PM in their local timezone
Without "Recipient's local time zone":
- If you schedule for 10:00 PM UTC
- UK user (GMT) receives at 10:00 PM β
- Pakistan user (PKT = UTC+5) receives at 3:00 AM β
- Not what you want!
Summary: #
| Notification Type | Timezone Handling | User Experience |
|---|---|---|
App Scheduled (scheduleWeekly, scheduleBatch) |
β Automatic - uses device timezone | Each user gets notification at specified local time |
| Firebase Console (with "Recipient's local time zone") | β Automatic - Firebase uses device timezone | Each user gets notification at specified local time |
| Firebase Console (without timezone option) | β Uses UTC | All users get notification at same UTC time (different local times) |
Immediate (show()) |
N/A - shows immediately | Shows immediately when received |
Technical Details: #
EasyNotify's TimezoneService:
- Calls
tz.initializeTimeZones()to load timezone database - Gets device timezone with
FlutterTimezone.getLocalTimezone() - Sets
tz.setLocalLocation()for accurate scheduling - All
scheduleWeeklyandscheduleBatchcalls usezonedSchedulewith local timezone
π± Platform Setup #
Android #
- Add to
android/app/build.gradle:
android {
defaultConfig {
minSdkVersion 21 // Required for notifications
}
}
- Add to
AndroidManifest.xml:
<manifest>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<application>
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>
iOS #
- Add to
ios/Runner/Info.plist:
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
- Enable capabilities in Xcode:
- Push Notifications
- Background Modes (Remote notifications)
π― Complete API Reference #
Initialization #
EasyNotify.init({
String androidIcon,
bool requestPermissionOnInit,
Function(NotificationResponse)? onNotificationTap,
Function(RemoteMessage)? onMessageOpened,
})
Show Notifications #
EasyNotify.show({required String title, required String body, String? payload, int? id})
Scheduling #
EasyNotify.scheduleWeekly({required int id, required int day, required int hour, required int minute, required String title, required String body, String? payload})
EasyNotify.scheduleBatch(List<ScheduleModel> schedules)
EasyNotify.scheduleOnce({required int id, required DateTime scheduledDate, required String title, required String body, String? payload})
Topics #
EasyNotify.subscribe(String topic)
EasyNotify.unsubscribe(String topic)
EasyNotify.subscribeMultiple(List<String> topics)
EasyNotify.unsubscribeMultiple(List<String> topics)
EasyNotify.setUserType(UserType userType)
EasyNotify.updateTopicsForUser({required bool isPremium})
Token #
EasyNotify.getToken() β Future<String?>
EasyNotify.deleteToken() β Future<void>
Cancel #
EasyNotify.cancel(int id)
EasyNotify.cancelAll()
Streams #
EasyNotify.onMessage β Stream<RemoteMessage>
EasyNotify.onTap β Stream<NotificationResponse>
EasyNotify.onMessageOpened β Stream<RemoteMessage>
Utility #
EasyNotify.getPendingNotifications() β Future<List<PendingNotificationRequest>>
EasyNotify.isInitialized β bool
π Models #
ScheduleModel #
ScheduleModel({
required List<int> days, // 1=Monday, 7=Sunday
required List<TimeOfDay> times,
String? title,
String? body,
String? payload,
})
UserType #
enum UserType {
free,
premium,
}
π Example App #
Check out the example directory for a complete working app demonstrating all features.
π Additional Documentation #
- Quick Start Guide - Get started in 5 minutes
- Timezone Guide - Complete timezone handling explanation
- Platform Setup Guide - Detailed Android/iOS configuration
- Architecture Documentation - Internal architecture and design
- Import Guide - Understanding exports and dependencies
β FAQ #
Q: When I schedule a notification for 10 PM, do all users get it at their local 10 PM? #
A: Yes! That's exactly how EasyNotify works.
For app-scheduled notifications (scheduleWeekly, scheduleBatch):
- Automatically uses each user's device timezone
- UK user gets it at 10 PM GMT
- Pakistan user gets it at 10 PM PKT
- USA user gets it at 10 PM EST
For Firebase Console campaigns:
- Select "Recipient's local time zone" when scheduling
- EasyNotify ensures the device timezone is correctly reported
- Each user receives at their local 10 PM
See the Timezone Guide for complete details.
Q: Do I need to add firebase_messaging or flutter_local_notifications to my pubspec.yaml? #
A: No! EasyNotify exports all the types you need. Just add:
dependencies:
easy_notify: ^1.0.0
firebase_core: ^2.24.2
See the Import Guide for details.
Q: How do I test notifications? #
A: Multiple ways:
- Immediate notification:
EasyNotify.show(title: 'Test', body: 'Testing') - Near-future scheduled: Schedule for 2 minutes from now
- Firebase Console: Use "Send test message" with your FCM token
- Check pending:
await EasyNotify.getPendingNotifications()
See the example app for a complete testing interface.
Q: Do notifications work when the app is closed? #
A: Yes!
- Scheduled local notifications fire even when app is closed
- FCM background messages are handled automatically
- EasyNotify sets up the background handler for you
Q: What about iOS permissions? #
A: Handled automatically! When you call EasyNotify.init(requestPermissionOnInit: true), it requests all necessary permissions on iOS. See Platform Setup Guide for details.
π€ Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
π License #
This project is licensed under the MIT License - see the LICENSE file for details.
π‘ Why EasyNotify? #
Other notification packages require complex setup with multiple files, manual timezone handling, and separate FCM/local notification management. EasyNotify wraps everything into one simple, opinionated API that just works.
Before EasyNotify:
- 50+ lines of boilerplate code
- Manual timezone calculations
- Separate FCM and local notification setup
- Complex background handler configuration
With EasyNotify:
- 3-5 lines of code
- Automatic timezone handling
- Unified API for all notification types
- Built-in background handling
Made with β€οΈ for the Flutter community