Issues with FCM notifications in a closed Flutter app

I am developing a Flutter application that utilizes Firebase for push notifications. The notifications work perfectly when the app is running in the background, but they do not arrive when the app is fully closed. My current setup is on Android 11.

Backend Code (Flask)

import firebase_admin
from firebase_admin import credentials, messaging

cred = credentials.Certificate("service-account.json")
firebase_admin.initialize_app(cred)

message = messaging.Message(
    notification=messaging.Notification(
        title="Alert!",
        body="Your push notification sent successfully!"
    ),
    data={
        "type": "general"
    },
    android=messaging.AndroidConfig(
        notification=messaging.AndroidNotification(
            title="Alert!",
            body="Your push notification sent successfully!",
            channel_id="default_channel",
            priority="high"
        ),
        priority="high"
    ),
    topic="users"
)

response = messaging.send(message)
print(response)

Flutter Code for Handling Notifications

@pragma('vm:entry-point')
Future<void> handleBackgroundMessages(RemoteMessage message) async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await Firebase.initializeApp();
  
  const AndroidNotificationChannel channel = AndroidNotificationChannel(
    'default_channel',
    'Default Notifications',
    description: 'Channel for app notifications.',
    importance: Importance.high
  );
  
  final FlutterLocalNotificationsPlugin localNotifications = FlutterLocalNotificationsPlugin();
  
  await localNotifications.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel);
  
  await localNotifications.initialize(
    InitializationSettings(
      android: AndroidInitializationSettings('icon')
    )
  );
  
  await localNotifications.show(
    0,
    message.notification?.title,
    message.notification?.body,
    NotificationDetails(
      android: AndroidNotificationDetails(
        'default_channel',
        'Default Notifications',
        importance: Importance.high
      )
    )
  );
}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await Firebase.initializeApp();
  
  final messaging = FirebaseMessaging.instance;
  
  await messaging.requestPermission(
    alert: true,
    badge: true,
    sound: true
  );
  
  FirebaseMessaging.onBackgroundMessage(handleBackgroundMessages);
  
  runApp(MyApp());
}

Subscribing to Topics

void subscribeUser() async {
  await FirebaseMessaging.instance.subscribeToTopic('users');
  
  if (mounted) {
    Navigator.of(context).pushReplacementNamed('/home');
  }
}

I’ve also tried common fixes like revising the Android manifest and adjusting battery settings, but the notifications don’t show up in the system tray when the app is terminated. I’m wondering if anyone has resolved this issue before.

that’s super frustrating! one thing to check is if your device has aggressive battery optimization enabled. brands like xiaomi and huawei can kill background processes, which messes up notifications. have you tried testing it on a different device or emulator?

try whitelisting the fcm service and give it auto-start permissions. newer androids cut background services on some devices, which might be why u dont see notifications. also, make sure ur app is excluded from battery optimizations.

Android’s battery optimization kills apps and blocks FCM messages, even with high priority settings. The system overrides your app config every time. I hit this same issue in production - Android does whitelist some apps automatically, but it won’t help when your app’s completely closed. Here’s what actually works: switch to data-only messages instead of notification messages. They get through more reliably. Also set up a proper background service for message handling. One more thing - if you’re testing on Xiaomi, OnePlus, or other phones with custom battery managers (MIUI, ColorOS, etc.), users need to manually allow background activity. The FCM setup looks fine but those manufacturer tweaks kill everything.