flutter-notifications
Skill1 starsChanged 18 days agoMITView on GitHub
Comprehensive guide and implementation runbook for Flutter notifications. Covers flutter_local_notifications 22+, Android 13+ permissions, Java 8/17 desugaring, Firebase Cloud Messaging (FCM) v1, cross-platform iOS APNs mapping, role-based notification dispatch (driver vs gatekeeper), and system tray vs in-app UI patterns.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- thienqo/flutter-skillstheir own version, first seen Nov 1, 2026
- thiennc-tesoglobal/flutter-skillstheir own version, first seen Aug 30, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- thiennc-tesoglobal/flutter-skills★ 16same name
- thienqo/flutter-skills★ 16same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository3 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- login-registerSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 33
Add the following permissions inside the <manifest> tag:
- Distinctive: line 159
Do not: write separate APNs device token management on your app server.
- Very specific: line 165
When your backend (Node.js / Python / Go) pushes notifications, use Google FCM HTTP v1 …
- Very specific: line 248
Use native SystemNotificationService to push notifications into the phone's status bar and drawer.
- Distinctive: line 252
Do NOT: use intrusive, top floating overlay banners that cover navigation bars, headers, or QR codes.
- Distinctive: line 253
DO use contextual, inline status changes:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Flutter Notifications: Complete Implementation & Architecture Runbook
This skill is the definitive reference for implementing system notifications, Firebase Cloud Messaging (FCM), and role-based notification routing in Flutter applications.
1. Core Architecture Overview
┌────────────────────────────────────────────────────────────────────────┐
│ FLUTTER NOTIFICATION STACK │
├───────────────────────────────────┬────────────────────────────────────┤
│ Native System Notifications │ Firebase Cloud Messaging (FCM) │
│ (flutter_local_notifications) │ (Cloud Push & Token Dispatch) │
├───────────────────────────────────┼────────────────────────────────────┤
│ • Native status bar & drawer │ • Unified FCM token for iOS/Android│
│ • Android 13+ POST_NOTIFICATIONS │ • Apple APNs translation via .p8 │
│ • Core Library Desugaring (JDK) │ • FCM HTTP v1 Backend Payload │
│ • High-priority alert channels │ • Topic & Token-based multicasting │
└───────────────────────────────────┴────────────────────────────────────┘2. System Notifications Setup (flutter_local_notifications 22+)
A. Android Manifest Configuration (android/app/src/main/AndroidManifest.xml)
Add the following permissions inside the <manifest> tag:
<!-- Required for Android 13+ (API level 33+) runtime push notifications -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<!-- Required for vibration with notification alerts -->
<uses-permission android:name="android.permission.VIBRATE" />B. Android Gradle Desugaring Requirement (android/app/build.gradle.kts)
flutter_local_notifications requires Java 8+ / Java 17 core library desugaring on Android. Without this, Gradle will fail with checkDebugAarMetadata.
android {
compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}C. flutter_local_notifications 22+ Syntax (Named Parameters)
[!IMPORTANT] In
flutter_local_notificationsv22+, bothinitialize()andshow()strictly use named parameters. Passing positional arguments causes compile-time errors.
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class SystemNotificationService {
static final SystemNotificationService _instance = SystemNotificationService._internal();
factory SystemNotificationService() => _instance;
SystemNotificationService._internal();
final FlutterLocalNotificationsPlugin _notificationsPlugin = FlutterLocalNotificationsPlugin();
bool _isInitialized = false;
Future<void> init() async {
if (_isInitialized) return;
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
const darwinSettings = DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
const initSettings = InitializationSettings(
android: androidSettings,
iOS: darwinSettings,
macOS: darwinSettings,
);
// Named parameter: settings
await _notificationsPlugin.initialize(
settings: initSettings,
onDidReceiveNotificationResponse: (NotificationResponse response) {
debugPrint('🔔 [Notification Tapped] Payload: ${response.payload}');
},
);
// Request runtime permission on Android 13+
if (!kIsWeb && Platform.isAndroid) {
final androidPlugin = _notificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>();
await androidPlugin?.requestNotificationsPermission();
}
_isInitialized = true;
}
Future<void> showNotification({
required int id,
required String title,
required String body,
String? payload,
String channelId = 'parkflow_channel',
String channelName = 'ParkFlow Updates',
}) async {
if (!_isInitialized) await init();
final androidDetails = AndroidNotificationDetails(
channelId,
channelName,
channelDescription: 'Real-time booking and security dispatch alerts',
importance: Importance.max,
priority: Priority.high,
showWhen: true,
enableVibration: true,
playSound: true,
);
const darwinDetails = DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
);
final notificationDetails = NotificationDetails(
android: androidDetails,
iOS: darwinDetails,
);
// Named parameters for show()
await _notificationsPlugin.show(
id: id,
title: title,
body: body,
notificationDetails: notificationDetails,
payload: payload,
);
}
}3. Firebase Cloud Messaging (FCM) Integration
A. Cross-Platform Token Architecture (iOS & Android)
- Do not write separate APNs device token management on your app server.
- On Android: Firebase SDK retrieves an FCM token via Google Play Services.
- On iOS: Firebase SDK exchanges the native Apple APNs token under the hood for a unified FCM token.
- Requirement for iOS: Upload the Apple APNs Auth Key (
.p8file) to Firebase Console (Project Settings -> Cloud Messaging -> Apple). Both platforms then use the exact same FCM token.
B. Backend FCM HTTP v1 Dispatch Payload
When your backend (Node.js / Python / Go) pushes notifications, use Google FCM HTTP v1 (https://fcm.googleapis.com/v1/projects/{projectId}/messages:send):
{
"message": {
"token": "RECIPIENT_FCM_TOKEN_HERE",
"notification": {
"title": "Parking Request Approved ✅",
"body": "Gatekeeper confirmed your slot at Silver Line. QR entry pass is active."
},
"data": {
"notification_type": "REQUEST_ACCEPTED",
"booking_id": "PKF-9281723",
"plot_id": "101",
"vehicle_number": "GJ03DH1450"
},
"android": {
"priority": "HIGH",
"notification": {
"channel_id": "parkflow_channel",
"sound": "default"
}
},
"apns": {
"payload": {
"aps": {
"sound": "default",
"badge": 1
}
}
}
}
}4. Role-Based Notification Routing: The Separation Rule
[!WARNING] The Golden Rule of Multi-Role Apps: An alert dispatched to an operator/gatekeeper must NEVER be displayed to the user/driver who initiated the request.
Matrix of Roles & Alert Targets:
| Event | Initiator | Intended Recipient | Delivery Target | Should User See It? |
| New Parking Request | Driver | Gatekeeper | fcm_gatekeeper_plot_{id} | ❌ NO (Never show on Driver App) |
| Booking Confirmed | Backend | Driver | Device Notification Drawer | ✅ YES (Driver Phone Status Bar) |
| Request Approved | Gatekeeper | Driver | Driver FCM + Status Bar | ✅ YES (Live ticket update + Notification) |
| Request Declined | Gatekeeper | Driver | Driver FCM + Status Bar | ✅ YES (Pass voided + Declining Reason) |
Enforcing Role Isolation in Code:
- Never pass the gatekeeper notification back into the user UI:
// ❌ BAD: Passing gatekeeper's dispatch object into the driver's ticket page ParkingTicketPage(gatekeeperNotification: gatekeeperNotif); // ✅ GOOD: Clean driver screen with live polling and driver system notification ParkingTicketPage(bookingId: bookingId, plot: plot); SystemNotificationService().notifyBookingConfirmed(plotName: plotName, ...); - Filter Reactive Notifiers:
// In GatekeeperNotificationService or repository listener: void _onNotificationReceived() { final notif = latestNotificationNotifier.value; if (notif == null) return; // Reject pending gatekeeper dispatch requests on user screens if (notif.isPending) return; if (notif.isAccepted) { ... } if (notif.isRejected) { ... } }
5. UI Placement: System Tray vs. In-App Overlay Banners
- System Tray / Phone Drawer (Recommended for Alerts):
- Use native
SystemNotificationServiceto push notifications into the phone's status bar and drawer. - Users expect notifications in their device's notification center (works when app is backgrounded or foregrounded).
- Use native
- Foreground State (Inside App Screens):
- Do NOT use intrusive, top floating overlay banners that cover navigation bars, headers, or QR codes.
- DO use contextual, inline status changes:
- Badge transitions:
PENDING➔CONFIRMED➔REJECTED(with VOID overlay). - Inline warning card with rejection reason inside the ticket card.
- Haptic feedback (
HapticFeedback.heavyImpact()).
- Badge transitions:
6. Live Sync Polling Fallback Pattern
Push notifications can occasionally be delayed by OS battery optimizations or poor network connectivity. Always pair push notifications with a lightweight live poll when viewing transactional screens (e.g. active parking pass):
Timer? _syncTimer;
void _startLiveSync() {
_syncTimer?.cancel();
_syncTimer = Timer.periodic(const Duration(seconds: 4), (_) async {
if (!mounted || _isChecking) return;
_isChecking = true;
try {
final res = await ApiService().getBookingStatus(widget.bookingId);
final status = res['status']?.toString().toUpperCase();
if (status == 'REJECTED') {
_applyRejection(res['reason']);
} else if (status == 'ACCEPTED') {
setState(() => _status = 'ACCEPTED');
}
} finally {
_isChecking = false;
}
});
}7. Troubleshooting & Gotchas Cheat Sheet
| Symptom / Error | Cause | Fix |
Too many positional arguments: 0 allowed, but 1 found in initialize | flutter_local_notifications 22+ API change | Use initialize(settings: initSettings, ...) |
Too many positional arguments: 0 allowed, but 4 found in show | flutter_local_notifications 22+ API change | Use show(id: id, title: title, body: body, notificationDetails: ...) |
Dependency requires core library desugaring to be enabled | Missing Java 8+ API desugaring for notification channels | Add isCoreLibraryDesugaringEnabled = true and desugar_jdk_libs in android/app/build.gradle.kts |
| Notifications not appearing on Android 13+ | Missing runtime permission | Call requestNotificationsPermission() on AndroidFlutterLocalNotificationsPlugin |
| Gatekeeper alert showing on driver phone | Dispatch object passed to user widget or broadcast via global notifier | Filter out isPending dispatches from driver listeners |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

