๐Ÿš€ Introduction

Firebase Cloud Messaging (FCM) is one of the most powerful and widely used tools for delivering real-time push notifications in mobile applications. For Flutter developers, FCM provides a reliable and scalable solution to send alerts, updates, promotional messages, reminders, and system notifications directly to Android or iOS devices. Because push notifications play a major role in user engagement and retention, integrating FCM into a Flutter app is essential for building modern, interactive, and user-focused applications.

With FCM, developers can send targeted messages to individual users, specific user groups, or entire audiencesโ€”all without setting up complex server infrastructure. Its seamless integration with Firebase services like Firestore and Cloud Functions makes it ideal for automating notifications based on real-time database changes, such as new orders, new messages, account activity, or status updates.

In short, FCM is a critical feature for any Flutter project aiming to deliver real-time communication, improve user engagement, and enhance the overall user experience while maintaining a smooth and cost-efficient backend system.

We will build a real-time notification system triggered by Firestoreโ€”ONLY for Android.

๐Ÿ”ฅ Part 1: Setup Firebase Messaging for Android Only
๐Ÿ— Step 1: Add Firebase to Your Flutter Android App

Run this command in your Flutter project in the terminal:

  • flutterfire configure
๐Ÿ›  Step 2: Add Required Dependencies

Add in pubspec.yaml:

dependencies:
firebase_core: ^3.0.0
firebase_messaging: ^15.0.0
cloud_firestore: ^5.0.0

 

โš™๏ธ Step 3: Android Configuration

1. Enable Firebase in android/build.gradle

buildscript {
    repositories {
        google()       // REQUIRED
        mavenCentral() // REQUIRED
    }
    dependencies {
        classpath("com.google.gms:google-services:4.4.2")
    }
}

2. Enable Google services in app/build.gradle

plugins {
    id("com.android.application")
    // START: FlutterFire Configuration
    id("com.google.gms.google-services")
    // END: FlutterFire Configuration
    id("kotlin-android")
    // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
    id("dev.flutter.flutter-gradle-plugin")
}

3. Add Permissions in AndroidManifest.xml

Inside:
android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

For Android 13+, notification permission is required.

4. Add Firebase Messaging Service Receiver

Inside <application> tag in AndroidManifest.xml:

<service
    android:name="io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingService"
    android:exported="false"
    tools:ignore="MissingClass">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>
๐Ÿ”” Part 2: Flutter Code for Android Push Notifications
Step 4: Initialize FCM in main.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'create_order_page.dart';

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  print("Background Message: ${message.notification?.title}");
}

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

  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'FCM + Firestore Android Only',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: NotificationHome(),
    );
  }
}

class NotificationHome extends StatefulWidget {
  @override
  _NotificationHomeState createState() => _NotificationHomeState();
}

class _NotificationHomeState extends State<NotificationHome> {
  String? token;

  @override
  void initState() {
    super.initState();
    initFCM();
  }

  void initFCM() async {
    FirebaseMessaging messaging = FirebaseMessaging.instance;

    // Request notification permission (Android 13+)
    await messaging.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );

    token = await messaging.getToken();
    print("ANDROID FCM Token: $token");

    // Save token to Firestore
    await FirebaseFirestore.instance
        .collection('users')
        .doc('admin')
        .set({'token': token});

    // Foreground notifications
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      print("Foreground Notification: ${message.notification?.title}");
      showDialog(
        context: context,
        builder: (_) => AlertDialog(
          title: Text(message.notification?.title ?? "Notification"),
          content: Text(message.notification?.body ?? ""),
        ),
      );
    });

    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("FCM Push Notifications (Android Only)"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("Your Device Token:", style: TextStyle(fontSize: 16)),
            SizedBox(height: 10),
            SelectableText(token ?? "Loading...", textAlign: TextAlign.center),
            SizedBox(height: 30),
            ElevatedButton(
              onPressed: () =>
                  Navigator.push(context, MaterialPageRoute(builder: (_) => CreateOrderPage())),
              child: Text("Create New Order"),
            )
          ],
        ),
      ),
    );
  }
}



๐Ÿ” Real-time Example UI (Order Creation)

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

class CreateOrderPage extends StatelessWidget {
  final TextEditingController nameCtrl = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Create New Order")),
      body: Padding(
        padding: EdgeInsets.all(20),
        child: Column(
          children: [
            TextField(
              controller: nameCtrl,
              decoration: InputDecoration(
                labelText: "Customer Name",
                border: OutlineInputBorder(),
              ),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              child: Text("Submit Order"),
              onPressed: () async {
                await FirebaseFirestore.instance.collection('orders').add({
                  "customerName": nameCtrl.text,
                  "createdAt": DateTime.now(),
                });

                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text("Order created successfully!")),
                );
              },
            )
          ],
        ),
      ),
    );
  }
}
๐ŸŽฏ Final Output

When you add a new order, Firestore triggers the Cloud Function.
A notification instantly appears on your Android device:

๐Ÿ“จ New Order Created!
Order from Ali

๐Ÿ™Œ Final Thank You Note

You did it! ๐ŸŽ‰
If you enjoyed this guide, donโ€™t forget to subscribe to our blog for more Flutter + Firebase tutorials. More real-world examples are coming soon!

Author

Write A Comment