Handling Push Notifications

Push notifications are an essential feature for modern mobile applications. They allow apps to communicate with users in real-time, even when the app is not running in the foreground. Whether it’s alerting users about new messages, updates, promotions, or reminders, push notifications improve engagement and retention.

In Flutter, handling push notifications requires understanding different app states (foreground, background, terminated), integrating with services like Firebase Cloud Messaging (FCM), and optionally using local notification packages for consistent cross-platform behavior. This post explores push notification handling in Flutter in detail, including setup, best practices, examples, and real-world use cases.


What Are Push Notifications

Push notifications are messages sent from a server to a client application, even when the app is not actively running. Unlike local notifications, which are scheduled by the app itself, push notifications are triggered remotely.

Key characteristics of push notifications include:

  • Remote Delivery: Notifications originate from a server or cloud service.
  • Device-Level Alerts: Delivered to mobile devices, tablets, or desktops.
  • Interactive: Users can act on notifications by tapping them, opening screens, or triggering actions.
  • Cross-Platform: Supported on Android and iOS devices.

Key Components in Flutter Push Notifications

  1. Firebase Cloud Messaging (FCM)
    Firebase Cloud Messaging is a free service that allows sending notifications to Android, iOS, and web platforms. It supports device targeting, topics, and condition-based messaging.
  2. Local Notifications Packages
    Packages like flutter_local_notifications allow Flutter apps to display notifications even when handling data locally or customizing notification appearance.
  3. Notification Handlers
    Functions that manage notification behavior depending on the app state:
    • Foreground: App is open and active.
    • Background: App is running but minimized.
    • Terminated: App is completely closed.

Setting Up Push Notifications in Flutter

1. Add Dependencies

Add required packages in pubspec.yaml:

dependencies:
  firebase_core: latest_version
  firebase_messaging: latest_version
  flutter_local_notifications: latest_version

2. Initialize Firebase

Initialize Firebase in main.dart:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

3. Configure iOS and Android

  • Android: Update AndroidManifest.xml for permissions.
  • iOS: Enable push notifications, configure APNs, and add capabilities in Xcode.

4. Request Notification Permissions

For iOS devices, request permission to display notifications:

FirebaseMessaging messaging = FirebaseMessaging.instance;

NotificationSettings settings = await messaging.requestPermission(
  alert: true,
  badge: true,
  sound: true,
);

if (settings.authorizationStatus == AuthorizationStatus.authorized) {
  print('User granted permission');
}

Handling Notifications in Different App States

1. Foreground Notifications

When the app is open, notifications do not appear in the system tray automatically. Use the onMessage listener to display them manually:

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  print('Message received: ${message.notification?.title}');
  // Display local notification
});

2. Background Notifications

Background messages are handled by a dedicated handler:

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print('Handling a background message: ${message.messageId}');
}

FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

The system tray automatically shows notifications, but you can customize behavior using local notifications.

3. Terminated State Notifications

When the app is closed, notifications appear in the system tray. You can detect if the app was opened via a notification:

FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
  if (message != null) {
// Navigate to specific screen
} });

Using Local Notifications

Combining FCM with flutter_local_notifications ensures consistent appearance and allows customization:

1. Initialize Local Notifications

final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@mipmap/ic_launcher');
final InitializationSettings initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (String? payload) async {
// Handle notification tap });

2. Display Notification

const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails('channel_id', 'channel_name',
    importance: Importance.max, priority: Priority.high);
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, message.notification?.title, message.notification?.body, platformChannelSpecifics,
payload: 'Custom data');

This approach ensures notifications look consistent on both Android and iOS.


Handling Notification Actions

You can trigger actions when users interact with notifications:

  • Navigate to a specific screen in the app.
  • Open a URL.
  • Execute a custom function.

Example:

FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
  Navigator.pushNamed(context, '/notificationScreen', arguments: message.data);
});

Topic-Based Notifications

FCM supports topics to send messages to a group of users:

await FirebaseMessaging.instance.subscribeToTopic('news');
await FirebaseMessaging.instance.unsubscribeFromTopic('news');

Messages sent to the news topic will be received by all subscribed devices.


Handling Data Messages

FCM allows sending data-only messages. These are not displayed automatically but can be used to trigger custom app behavior:

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  if (message.data.isNotEmpty) {
// Handle custom data
} });

This is useful for in-app updates, analytics, or silent notifications.


Customizing Notification Appearance

Using flutter_local_notifications, you can customize:

  • Icons
  • Sounds
  • Colors
  • Priority and importance
  • Notification grouping

Example:

AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
  'channel_id',
  'channel_name',
  importance: Importance.max,
  priority: Priority.high,
  color: Colors.blue,
  playSound: true,
  icon: '@mipmap/ic_launcher',
);

Real-World Examples

1. Chat App

  • New messages trigger push notifications.
  • Foreground messages show a custom in-app banner.
  • Background messages appear in the system tray.

2. E-Commerce App

  • Promotions, discounts, and order updates are sent via push notifications.
  • Tapping a notification opens the product page directly.

3. News App

  • Topic-based notifications send breaking news alerts.
  • Users subscribe to categories like sports, politics, or entertainment.

4. Reminder App

  • Scheduled notifications remind users of tasks or events.
  • Local notifications ensure reminders appear even without an internet connection.

Advantages of Push Notifications in Flutter

  1. User Engagement – Keeps users informed and engaged.
  2. Cross-Platform – Works seamlessly on Android and iOS.
  3. Real-Time Updates – Users receive instant alerts for messages, events, or promotions.
  4. Customizable – Local notifications allow rich customization.
  5. Flexible – Supports foreground, background, and terminated states.
  6. Integrates with Analytics – Track notification opens and user actions.

Limitations and Challenges

  1. Platform Differences – iOS and Android handle notifications differently.
  2. Permission Management – Users may deny notification permissions.
  3. Network Dependency – FCM requires an active internet connection to deliver messages.
  4. Battery Considerations – Excessive push notifications can impact device battery.
  5. Message Size Limits – FCM messages have size limitations for payloads.
  6. Complex Background Handling – Background and terminated states require careful configuration.

Best Practices for Push Notifications

  1. Segment Users – Use topics or conditions to send relevant notifications.
  2. Personalize Messages – Increase engagement with personalized content.
  3. Respect User Preferences – Allow users to opt-in or opt-out of notifications.
  4. Avoid Overuse – Excessive notifications can lead to app uninstalls.
  5. Use Actionable Notifications – Include buttons or links to drive user interaction.
  6. Test Across Devices – Ensure notifications behave correctly on different Android and iOS versions.
  7. Monitor Analytics – Track delivery, opens, and conversions.

Combining Push and Local Notifications

For consistent behavior across platforms:

  • Use FCM for remote delivery.
  • Use flutter_local_notifications to display notifications in the foreground.
  • Customize appearance and actions using local notification capabilities.
  • Handle notification taps to navigate users to specific screens or perform actions.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *