Flutter Notification Listener
February 13, 2026 · View on GitHub
Flutter Notification Listener
A powerful Flutter plugin for listening to all incoming notifications on Android
Features · Installation · Quick Start · API Reference · Contributing
✨ Features
|
🔔 Real-time Listening Capture all system notifications as they arrive, from any app installed on the device. |
🎯 Simple API Clean and intuitive API design. Access notification fields with ease. |
|
⚡ Background Execution Run Dart code in the background. Auto-start service after device reboot. |
🎮 Interactive Tap notifications, trigger actions, and even auto-reply to messages directly from Flutter. |
Compatibility
| Android Version | API Level | Status |
|---|---|---|
| Android 14 | API 34 | ✅ Fully Supported |
| Android 13 | API 33 | ✅ Fully Supported |
| Android 12 | API 31-32 | ✅ Fully Supported |
| Android 11 and below | API ≤ 30 | ✅ Fully Supported |
📦 Installation
Add the dependency to your pubspec.yaml:
dependencies:
flutter_notification_listener: ^1.4.0
Then run:
flutter pub get
🚀 Quick Start
Step 1: Configure Android Manifest
Add the notification listener service inside the <application> tag:
<service
android:name="im.zoe.labs.flutter_notification_listener.NotificationsHandlerService"
android:label="Flutter Notifications Handler"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:exported="true"
android:foregroundServiceType="specialUse">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="notification_listener"/>
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
Add required permissions:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/>
Note: For Android 13+, request the
POST_NOTIFICATIONSpermission at runtime before starting the foreground service.
Step 2: Initialize the Plugin
import 'package:flutter_notification_listener/flutter_notification_listener.dart';
void onData(NotificationEvent event) {
print('${event.packageName}: ${event.title} - ${event.text}');
}
Future<void> initPlatformState() async {
NotificationsListener.initialize();
NotificationsListener.receivePort?.listen((evt) => onData(evt));
}
Step 3: Start the Service
Future<void> startListening() async {
final hasPermission = await NotificationsListener.hasPermission ?? false;
if (!hasPermission) {
NotificationsListener.openPermissionSettings();
return;
}
final isRunning = await NotificationsListener.isRunning ?? false;
if (!isRunning) {
await NotificationsListener.startService(
foreground: true,
title: "Listening for notifications",
);
}
}
📖 See the example app for a complete implementation.
📖 Usage Guide
Auto-start After Reboot
Register a broadcast receiver to automatically restart the service after device reboot:
<receiver
android:name="im.zoe.labs.flutter_notification_listener.RebootBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Add the boot permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Background Processing
For reliable background execution, use a static callback function:
@pragma('vm:entry-point')
static void _callback(NotificationEvent evt) {
// Persist data immediately
db.save(evt);
// Forward to UI thread if needed
final send = IsolateNameServer.lookupPortByName("_listener_");
send?.send(evt);
}
Future<void> initPlatformState() async {
NotificationsListener.initialize(callbackHandle: _callback);
}
Important: The
@pragma('vm:entry-point')annotation is required for Flutter 3.x to prevent the function from being stripped in release builds.
Interactive Notifications
Tap a notification:
void onData(NotificationEvent event) {
if (event.canTap) {
event.tap();
}
}
Auto-reply to messages:
void onData(NotificationEvent event) {
for (final action in event.actions ?? []) {
if (action.semantic == 1) { // SEMANTIC_ACTION_REPLY
final inputs = <String, dynamic>{};
for (final input in action.inputs ?? []) {
inputs[input.resultKey ?? ''] = "Auto-reply from Flutter";
}
action.postInputs(inputs);
}
}
}
Customize Service Notification
await NotificationsListener.startService(
foreground: true,
title: "My App",
description: "Listening for notifications...",
);
📚 API Reference
NotificationEvent
| Property | Type | Description |
|---|---|---|
uniqueId | String | Unique identifier generated from key |
packageName | String | Source application package name |
title | String? | Notification title |
text | String? | Notification body text |
timestamp | int | Post time (milliseconds since epoch) |
channelId | String? | Notification channel ID (API 26+) |
largeIcon | Uint8List? | Large icon as bytes |
canTap | bool | Whether notification has a tap action |
actions | List<Action>? | Available notification actions |
raw | Map<String, dynamic> | Raw notification data |
Methods:
| Method | Returns | Description |
|---|---|---|
tap() | Future<bool> | Trigger the notification's tap action |
getFull() | Future<dynamic> | Get complete notification data |
Action
| Property | Type | Description |
|---|---|---|
id | int | Action index |
title | String? | Action button text |
semantic | int | Semantic type (see below) |
inputs | List<ActionInput>? | Input fields for reply actions |
Semantic Types:
| Constant | Value | Description |
|---|---|---|
SEMANTIC_ACTION_NONE | 0 | No semantic |
SEMANTIC_ACTION_REPLY | 1 | Quick reply |
SEMANTIC_ACTION_MARK_AS_READ | 2 | Mark as read |
SEMANTIC_ACTION_MARK_AS_UNREAD | 3 | Mark as unread |
SEMANTIC_ACTION_DELETE | 4 | Delete |
SEMANTIC_ACTION_ARCHIVE | 5 | Archive |
SEMANTIC_ACTION_MUTE | 6 | Mute |
SEMANTIC_ACTION_UNMUTE | 7 | Unmute |
NotificationsListener
| Method | Description |
|---|---|
initialize({callbackHandle}) | Initialize the plugin |
hasPermission | Check notification access permission |
isRunning | Check if service is running |
openPermissionSettings() | Open system permission settings |
startService({...}) | Start the listener service |
stopService() | Stop the listener service |
promoteToForeground({...}) | Promote service to foreground |
demoteToBackground() | Demote service to background |
⚠️ Known Issues
- Service may fail to start after reboot if not running in foreground mode.
💖 Support
If you find this plugin useful, please consider:
- ⭐ Starring the repository
- 🐛 Reporting bugs
- 💡 Suggesting new features
- 🤝 Contributing code
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your 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
Made with ❤️ by Zoe