If you’re creating a mobile app, understanding Local notifications in Flutter is essential because they allow your app to deliver instant, offline alerts to users. In Flutter, adding local notifications is surprisingly simple. In this guide, we’ll walk through how to integrate flutter_local_notifications in both Android and iOS using clean and beginner-friendly steps.
Project Structure
We will make the project structure as simple as we can in this small project
flutter_notifications_/ │── android/ │── ios/ │── lib/ │ ├── main.dart │ ├── homes_creen.dart │ ├── notification_service.dart │── pubspec.yaml
Setting Up Dependencies
First, add the required dependencies to your pubspec.yaml file
flutter_local_notifications: ^19.5.0
Only the flutter_local_notifications package is required for us to achieve it
Configurations
For Android, the package itself mentions that there will be no required steps for local instance notification, but in the latest Flutter versions, you may need to add a few extra lines to your build.gradle.kts file. This step isn’t required for everyone, but some developers may run into errors if it’s missing.
Inside the android/app/build.gradle.kts
compileOptions {
isCoreLibraryDesugaringEnabled = true // add this line
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
// also add this dependency
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}
For iOS, you need to set up a small configuration. First, import flutter_local_notifications at the top of your AppDelegate.swift file along with Flutter and UIKit. After that, add the required initialization lines. For the full setup, you can follow the official documentation.
ios/Runner/AppDelegate.swift
import Flutter
import UIKit
// Add this line --- (1)
import flutter_local_notifications
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// add this lis two --- (2)
// This is required to make any communication available in the action isolate.
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
GeneratedPluginRegistrant.register(with: self)
// last add this line --- (3)
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
If you have faced any error while adding this tree line, then just copy this code and replace your AppDelegate.swift file.
Now, the package addition and configuration part is completed. Next, let’s start the process to achieve a local notification.
Notification Service
To make notification handling easier and more reusable, I created a dedicated NotificationService class. This service takes care of initializing the plugin for both Android and iOS, requesting permissions, and providing simple methods to show or cancel notifications. You can use this class anywhere in your app to trigger notifications with just one function call.
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class NotificationService {
final FlutterLocalNotificationsPlugin _notificationsPlugin =
FlutterLocalNotificationsPlugin();
// Initialize notifications
Future<void> initialize() async {
// Android initialization settings
const AndroidInitializationSettings androidSettings =
AndroidInitializationSettings('@mipmap/ic_launcher');
// iOS initialization settings
const DarwinInitializationSettings iosSettings =
DarwinInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
// Combined initialization settings
const InitializationSettings initializationSettings =
InitializationSettings(android: androidSettings, iOS: iosSettings);
// Initialize the plugin
await _notificationsPlugin.initialize(initializationSettings);
}
// Show a simple notification
Future<void> showNotification({
int id = 0,
String title = 'Notification',
String body = 'This is a notification message',
}) async {
// Android notification details
const AndroidNotificationDetails androidDetails =
AndroidNotificationDetails(
'default_channel',
'Default Channel',
channelDescription: 'This is the default notification channel',
importance: Importance.max,
priority: Priority.high,
showWhen: true,
);
// iOS notification details
const DarwinNotificationDetails iosDetails = DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
);
// Combined notification details
const NotificationDetails notificationDetails = NotificationDetails(
android: androidDetails,
iOS: iosDetails,
);
// Show the notification
await _notificationsPlugin.show(id, title, body, notificationDetails);
}
// Cancel a specific notification
Future<void> cancelNotification(int id) async {
await _notificationsPlugin.cancel(id);
}
// Cancel all notifications
Future<void> cancelAllNotifications() async {
await _notificationsPlugin.cancelAll();
}
}
Notification Service Initialisation
Before running the app, we need to initialize our notification service. This makes sure the plugin is fully set up for both Android and iOS. So inside the main() function, we call NotificationService().initialize() before runApp().
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize notification service
await NotificationService().initialize();
runApp(const MyApp());
}
Displaying a Notification in Flutter
Once the notification service is initialized, we can trigger a notification from anywhere in our app. In the example below, I’ve created a simple screen with a button. When the user taps the button, the NotificationService().showNotification() method is called, and a notification appears immediately.
class NotificationScreen extends StatelessWidget {
const NotificationScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Notification Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
// Simply call the notification service
NotificationService().showNotification(
title: 'Hello!',
body: 'This is your notification message',
);
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 20),
),
child: const Text(
'Show Notification',
style: TextStyle(fontSize: 18),
),
),
),
);
}
}
Finally, after all this process, we can easily get a notification when we click on the button.
Conclusiong
Flutter makes notifications incredibly straightforward thanks to the flutter_local_notifications package. Once the initial setup is done, you can easily extend it to scheduled reminders, custom sounds, or even payload navigation.
If you plan to add daily reminders, repeating notifications, or background tasks, this same foundation works perfectly—you just build on top of it.
This basic approach is reliable, beginner-friendly, and production-ready. If you also want to know about Firebase push notifications, then read this blog.





