platform_local_notifications 2.1.0
platform_local_notifications: ^2.1.0 copied to clipboard
A comprehensive cross-platform local notifications plugin for Flutter supporting Android, iOS, Web, Windows, macOS, and Linux with chat-style notifications and interactive actions.
Platform Local Notifications #
A comprehensive cross-platform local notifications plugin for Flutter supporting Android, iOS, Web, Windows, macOS, and Linux with chat-style notifications and interactive actions.
Features #
- 🌍 Cross-Platform Support: Works on all major Flutter platforms
- 💬 Chat Notifications: Interactive notifications with reply functionality
- 🔔 Standard Notifications: Simple, customizable notifications
- 🎯 Action Handling: Handle notification clicks, replies, and mark-as-read actions
- 🔐 Permission Management: Automatic permission requests for each platform
- 🖼️ Image Caching: Automatic caching of user profile images
- 📱 Platform Optimization: Platform-specific optimizations and features
Supported Platforms #
Platform | Standard Notifications | Chat Notifications | Actions |
---|---|---|---|
Android | ✅ | ✅ | ✅ |
iOS | ✅ | ✅ | ✅ |
Web | ✅ | ⚠️ (Limited) | ❌ |
Windows | ✅ | ❌ | ❌ |
macOS | ✅ | ❌ | ❌ |
Linux | ✅ | ❌ | ❌ |
Installation #
Add the dependency to your pubspec.yaml
:
dependencies:
platform_local_notifications: ^2.1.0
Platform Configuration #
Android Setup #
For notification actions (reply, mark as read) to work properly on Android, you must add the following receiver to your android/app/src/main/AndroidManifest.xml
file within the <application>
tag:
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
Example AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="your_app_name"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<!-- Your existing activity configuration -->
<activity android:name=".MainActivity" ... >
<!-- Activity configuration -->
</activity>
<!-- Add this receiver for notification actions -->
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
</application>
</manifest>
⚠️ Important: Without this receiver, notification actions (reply, mark as read) will not work properly on Android devices.
Quick Start #
1. Initialize the Service #
import 'package:platform_local_notifications/platform_local_notifications.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await PlatformNotifier.initialize(appName: 'My App');
runApp(MyApp());
}
2. Request Permissions #
Future<void> requestNotificationPermissions() async {
final isGranted = await PlatformNotifier.requestPermissions();
if (isGranted == true) {
print('Notification permissions granted');
} else {
print('Notification permissions denied');
}
}
3. Show a Standard Notification #
Future<void> showSimpleNotification() async {
final notificationModel = NotificationModel(
id: DateTime.now().millisecondsSinceEpoch,
title: 'Hello!',
body: 'This is a simple notification',
payload: 'notification_data',
);
await PlatformNotifier.showNotification(model: notificationModel);
}
4. Show a Chat Notification #
Future<void> showChatNotification() async {
final chatModel = ChatNotificationModel(
id: DateTime.now().millisecondsSinceEpoch,
title: 'New Message',
body: 'Hello! How are you?',
userImageUrl: 'https://example.com/avatar.jpg',
userName: 'John Doe',
conversationTitle: 'Group Chat',
payload: 'chat_data',
);
await PlatformNotifier.showChatNotification(model: chatModel);
}
5. Handle Notification Actions #
void setupNotificationListeners() {
PlatformNotifier.actionStream.listen((action) {
switch (action.runtimeType) {
case NotificationClickAction _:
final clickAction = action as NotificationClickAction;
print('Notification clicked: ${clickAction.payload}');
break;
case NotificationReplyAction _:
final replyAction = action as NotificationReplyAction;
print('User replied: ${replyAction.replyText}');
print('Payload: ${replyAction.payload}');
break;
case NotificationMarkReadAction _:
final markReadAction = action as NotificationMarkReadAction;
print('Notification marked as read: ${markReadAction.payload}');
break;
}
});
}
6. Check App Launch Details #
Future<void> checkAppLaunchDetails() async {
final launchDetails = await PlatformNotifier.appLaunchNotification;
if (launchDetails != null) {
print('App was launched from notification!');
print('Did notification launch app: ${launchDetails.didNotificationLaunchApp}');
print('Payload: ${launchDetails.notificationResponse?.payload}');
print('Action ID: ${launchDetails.notificationResponse?.actionId}');
print('Input: ${launchDetails.notificationResponse?.input}');
} else {
print('App was not launched from a notification');
}
}
Advanced Usage #
Custom Configuration #
final customConfig = NotificationData(
androidNotificationChannel: AndroidNotificationChannel(
'custom_channel',
'Custom Notifications',
importance: Importance.high,
),
initializationSettingsAndroid: AndroidInitializationSettings('@mipmap/ic_launcher'),
initializationSettingsDarwin: DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
),
);
await PlatformNotifier.initialize(
appName: 'My App',
notificationData: customConfig,
);
Custom Notification Details #
final notificationModel = NotificationModel(
id: 1,
title: 'Custom Notification',
body: 'With custom styling',
payload: 'custom_data',
androidDetails: AndroidNotificationDetails(
'custom_channel',
'Custom Channel',
channelDescription: 'Custom notification channel',
importance: Importance.max,
priority: Priority.high,
showWhen: true,
enableVibration: true,
playSound: true,
),
iosDetails: DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
badgeNumber: 1,
),
macOsDetails: DarwinNotificationDetails(
presentSound: true,
subtitle: 'Custom Subtitle',
presentBadge: true,
),
);
await PlatformNotifier.showNotification(model: notificationModel);
Custom Chat Notification #
final chatModel = ChatNotificationModel(
id: 1,
title: 'New Message',
body: 'Hello from John!',
userImageUrl: 'https://example.com/john.jpg',
userName: 'John Doe',
conversationTitle: 'Team Chat',
markAsReadLabel: 'Mark as Read',
replyLabel: 'Quick Reply',
replyHint: 'Type your reply...',
messages: [
Message(
'Hello from John!',
DateTime.now().subtract(Duration(minutes: 5)),
Person(name: 'John Doe'),
),
Message(
'How are you doing?',
DateTime.now(),
Person(name: 'John Doe'),
),
],
payload: 'chat_123',
);
await PlatformNotifier.showChatNotification(model: chatModel);
Cancel Notifications #
// Cancel a specific notification
await PlatformNotifier.cancelNotification(123);
// Cancel a notification with tag
await PlatformNotifier.cancelNotification(123, tag: 'chat_notification');
// Cancel all notifications
await PlatformNotifier.cancelAllNotifications();
Platform-Specific Features #
Android #
- Custom notification channels
- Messaging style notifications
- Action buttons (Reply, Mark as Read)
- Rich notifications with images
- Priority and importance settings
iOS #
- Badge numbers
- Sound and alert settings
- Critical notifications support
- Custom notification categories
Web #
- Browser notifications
- Permission handling
- Limited chat functionality
Desktop (Windows/macOS/Linux) #
- Native desktop notifications
- System integration
- Custom notification sounds
Error Handling #
The plugin includes comprehensive error handling:
try {
await PlatformNotifier.showNotification(model: notificationModel);
} on StateError catch (e) {
print('Service not initialized: $e');
} on ArgumentError catch (e) {
print('Invalid notification model: $e');
} catch (e) {
print('Unexpected error: $e');
}
Best Practices #
1. Initialize Early #
Always initialize the service in your app's startup:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await PlatformNotifier.initialize(appName: 'My App');
runApp(MyApp());
}
2. Handle Permissions #
Request permissions early and handle denied cases:
Future<void> setupNotifications() async {
final isGranted = await PlatformNotifier.requestPermissions();
if (isGranted != true) {
// Show dialog explaining why notifications are needed
showPermissionDialog();
}
}
3. Use Unique IDs #
Always use unique IDs for notifications to avoid conflicts:
final notificationId = DateTime.now().millisecondsSinceEpoch;
// or
final notificationId = Random().nextInt(1000000);
4. Validate Models #
The plugin automatically validates notification models, but you can also validate manually:
final model = NotificationModel(
id: 1,
title: 'Test',
body: 'Test body',
);
if (model.isValid) {
await PlatformNotifier.showNotification(model: model);
}
5. Dispose Properly #
Dispose the service when your app is terminated:
@override
void dispose() {
PlatformNotifier.dispose();
super.dispose();
}
Troubleshooting #
Common Issues #
-
Notifications not showing on Android
- Ensure notification channel is created
- Check notification permissions
- Verify app is not in battery optimization
-
Chat notifications not working
- Only supported on mobile platforms (Android/iOS)
- Ensure proper image URL format
- Check network connectivity for image loading
-
Actions not working
- Ensure proper isolate communication setup
- Check action IDs match constants
- Verify background notification handling
-
Web notifications not working
- Ensure HTTPS in production
- Check browser notification permissions
- Verify user interaction before showing notifications
Debug Mode #
Enable debug logging:
// The plugin automatically logs debug information
// Check console output for initialization and error messages
API Reference #
Classes #
PlatformNotifier
- Main entry point for notification operationsPlatformNotificationService
- Core service implementationNotificationModel
- Standard notification configurationChatNotificationModel
- Chat-style notification configurationNotificationData
- Plugin configuration dataBaseNotificationAction
- Base class for notification actionsNotificationClickAction
- Click action eventNotificationReplyAction
- Reply action eventNotificationMarkReadAction
- Mark as read action event
Methods #
PlatformNotifier
initialize(appName, notificationData)
- Initialize the servicerequestPermissions()
- Request notification permissionsshowNotification(model, context)
- Show standard notificationshowChatNotification(model, context)
- Show chat notificationcancelNotification(id, tag)
- Cancel specific notificationcancelAllNotifications()
- Cancel all notificationsappLaunchNotification
- Get app launch details from notificationdispose()
- Dispose the service
NotificationModel
copyWith(...)
- Create a copy with modified fieldsisValid
- Check if the model is valid
ChatNotificationModel
copyWith(...)
- Create a copy with modified fieldsisValid
- Check if the model is valid
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.
Changelog #
2.0.0 #
- Complete code refactoring and reorganization
- Improved error handling and validation
- Better documentation and examples
- Enhanced type safety
- Cleaner API design
- Platform-specific optimizations
1.0.5 #
- Initial release with basic functionality