Local Notifications in Flutter

0

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.

Previous articleFlutter AdMob Integration: Banner, Interstitial, and Rewarded Ads

LEAVE A REPLY

Please enter your comment!
Please enter your name here