Push Notifications in Flutter

Push Notifications in Flutter

Push notification using Firebase messaging

Push notifications are messages sent from a server to a user’s device, even when the app is not actively in use. They are used to engage users by sending alerts, updates, promotions, or other relevant content.

How Push Notifications Work

  1. User Registers for Notifications – The app requests permission from the user.

  2. Device Gets a Token – If permission is granted, the device is assigned a unique token by Firebase Cloud Messaging (FCM).

  3. Server Sends Notification – A backend (or Firebase console) sends a push notification using the device token.

  4. Device Receives the Notification – The notification is handled based on whether the app is in the foreground, background, or terminated.

Types of Push Notifications

  1. Foreground Notifications – Shown when the app is open. These need manual handling in Flutter.

  2. Background Notifications – Delivered directly to the system tray when the app is in the background.

  3. Silent Notifications – Do not alert the user but can update the app’s data in the background.

Why Use Push Notifications?

  • Improve user engagement

  • Deliver timely updates

  • Re-engage inactive users

  • Notify users about important events

To set up push notifications in Flutter using only Dart and integrate them with the Awesome Notifications package, you can follow these steps. This guide assumes you are using Firebase for push notifications, but you will write all the code in Dart without a custom backend.

Step 1: Set Up Firebase

  1. Add Firebase to Your Project:

    • Go to the Firebase Console.

    • Create a new project or use an existing one.

    • Add an Android/iOS app to your Firebase project.

    • Download the google-services.json (for Android) and GoogleService-Info.plist (for iOS) and add them to your Flutter project.

  2. Add Firebase Dependencies:

    Add the following dependencies to your pubspec.yaml file:

     dependencies:
       firebase_core: latest_version
       firebase_messaging: latest_version
       awesome_notifications: latest_version
    
  3. Initialize Firebase:

    In your main.dart file, initialize Firebase:

     import 'package:firebase_core/firebase_core.dart';
     import 'package:flutter/material.dart';
     import 'package:awesome_notifications/awesome_notifications.dart';
    
     void main() async {
       WidgetsFlutterBinding.ensureInitialized();
       await Firebase.initializeApp();
       AwesomeNotifications().initialize(
         'resource://drawable/res_app_icon', // Your app icon
         [
           NotificationChannel(
             channelKey: 'basic_channel',
             channelName: 'Basic notifications',
             channelDescription: 'Notification channel for basic tests',
             defaultColor: Color(0xFF9D50DD),
             ledColor: Colors.white,
           )
         ],
       );
       runApp(MyApp());
     }
    
     class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return MaterialApp(
           home: HomeScreen(),
         );
       }
     }
    

Step 2: Configure Firebase Messaging

  1. Request Notification Permissions:

    Add the following code to request notification permissions:

     import 'package:firebase_messaging/firebase_messaging.dart';
    
     class NotificationService {
       final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
    
       Future<void> initialize() async {
         // Request permission for iOS
         NotificationSettings settings = await _firebaseMessaging.requestPermission(
           alert: true,
           badge: true,
           sound: true,
         );
    
         if (settings.authorizationStatus == AuthorizationStatus.authorized) {
           print('User granted permission');
         } else {
           print('User declined or has not accepted permission');
         }
       }
     }
    
  2. Handle Incoming Messages:

    Configure Firebase Messaging to handle incoming messages:

     class NotificationService {
       final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
    
       NotificationService() {
         _firebaseMessaging.onMessage.listen((RemoteMessage message) {
           // Handle foreground messages
           print('Got a message whilst in the foreground: ${message.messageId}');
           if (message.notification != null) {
             print('Message also contained a notification: ${message.notification}');
             AwesomeNotifications().createNotification(
               content: NotificationContent(
                 id: 10,
                 channelKey: 'basic_channel',
                 title: message.notification?.title,
                 body: message.notification?.body,
               ),
             );
           }
         });
    
         _firebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
           // Handle when the user taps on the notification
           print('A new onMessageOpenedApp event was published!');
           print(message.data);
         });
       }
     }
    

Step 3: Send a Test Notification

  1. Get the Device Token:

    Retrieve the device token to send a test notification:

     class NotificationService {
       final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
    
       Future<void> getToken() async {
         String? token = await _firebaseMessaging.getToken();
         print("Firebase Messaging Token: $token");
       }
     }
    
  2. Send a Test Notification using Firebase Cloud Messaging (FCM):

    Use the Firebase Console or Postman to send a test notification using the device token:

    • Firebase Console:

      • Go to the Firebase Console.

      • Navigate to "Cloud Messaging".

      • Click "Send your first message".

      • Enter the notification details and target the specific device using the token.

    • Postman:

      Send a POST request to the FCM endpoint with the device token:

        POST https://fcm.googleapis.com/fcm/send
        Headers:
        - Authorization: key=YOUR_SERVER_KEY
        - Content-Type: application/json
      
        Body:
        {
          "to": "DEVICE_TOKEN",
          "notification": {
            "title": "Hello",
            "body": "This is a test notification"
          }
        }
      

Step 4: Integrate the Notification Service in Your App

  1. Initialize the Notification Service:

     void main() async {
       WidgetsFlutterBinding.ensureInitialized();
       await Firebase.initializeApp();
       AwesomeNotifications().initialize(
         'resource://drawable/res_app_icon', // Your app icon
         [
           NotificationChannel(
             channelKey: 'basic_channel',
             channelName: 'Basic notifications',
             channelDescription: 'Notification channel for basic tests',
             defaultColor: Color(0xFF9D50DD),
             ledColor: Colors.white,
           )
         ],
       );
    
       NotificationService notificationService = NotificationService();
       await notificationService.initialize();
       await notificationService.getToken();
    
       runApp(MyApp());
     }
    
  2. Use the Notification Service in Your Widgets:

     class HomeScreen extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return Scaffold(
           appBar: AppBar(
             title: Text('Home Screen'),
           ),
           body: Center(
             child: Text('Welcome to Flutter Notifications!'),
           ),
         );
       }
     }
    

    PS: To learn about awesome notifications plugins use this:

    https://atuoha.hashnode.dev/local-notification-in-flutter-using-awesomenotifications or their official docs at https://pub.dev/packages/awesome_notifications

Did you find this article valuable?

Support Flutter Aware by becoming a sponsor. Any amount is appreciated!