Search code examples
iosflutterpush-notificationfirebase-cloud-messaging

Flutter push notifications using FCM not working on iOS


I have been attempting for weeks to get push notifications to work properly on iOS to no avail. I have combed through the documentation to verify my config. The push notifications are working properly for Android however.

I have also tested sending messages directly from the firebase messaging console to IOS and am still unsuccessful. I've also tried many of the suggestions in previous stack overflow posts with no success.

Flutter IOS FCM push notification not coming into notification bar

Flutter Push notification not displaying on IOS

https://github.com/FirebaseExtended/flutterfire/issues/1677

iOS FirebaseCloudMessaging Notifications not working in Debug / Test Flight nor Release

I am using a physical iPhone 12 on iOS 14.6. The version of Xcode I'm on is 12.5. Xcode is configured as follows.

Signing and Capabilities Signing and Capabilities

Signing Signing

Code for the app delegate file

import UIKit
import Flutter
import Firebase
import FirebaseMessaging
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
  override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

   Messaging.messaging().apnsToken = deviceToken
   super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
 }
}

Code for how push notifications are requested

Future<void> notficationsPermission () async {
  FirebaseMessaging messaging = FirebaseMessaging.instance;

NotificationSettings settings = await messaging.requestPermission(
  alert: true,
  announcement: true,
  badge: true,
  carPlay: false,
  criticalAlert: true,
  provisional: false,
  sound: true,
);


print('User granted permission: ${settings.authorizationStatus}');


String uid = Pref.getString(Keys.USER_ID);
var databaseReference = FirebaseDatabase.instance.reference();
if(settings.authorizationStatus == AuthorizationStatus.authorized){
  notficationStatus = true; 
 await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
   
  alert: true, // Required to display a heads up notification
  badge: true,
  sound: true,
);
}

else{
  notficationStatus = false;  
}
}
}

Snippet of how notifications are configured

return admin.messaging().sendToTopic(
                            topicName, {
                              android: {
                                priority: "high",
                              },
                              // Add APNS (Apple) config
                              apns: {
                                payload: {
                                  aps: {
                                    contentAvailable: true,
                                  },
                                },
                                headers: {
                                  "apns-push-type": "background",
                                  "apns-priority": "5", // Must be `5` when `contentAvailable` is set to true.
                                  "apns-topic": "io.flutter.plugins.firebase.messaging", // bundle identifier
                                },
                              },
                              notification: {
                                title: snapshot2.val().group_name +
                                  ": new chat message",
                                body: name +":"+snapshot.val().message,
                                clickAction: "FLUTTER_NOTIFICATION_CLICK",
                              },
                            });

I also having the following in my Info.plist.

<key>FirebaseAppDelegateProxyEnabled</key>
    <string>0</string>

Solution

  • I finally figured this out but forgot to post the answer! in my index.js

    exports.chatNotfi = functions.database.ref("messages/{gId}/{chat}")
    .onCreate((snapshot, context)=>{
      const groupId = context.params.gId;
      console.log("Group id:" + groupId);
      const topicName = groupId + "chat";
      console.log("topic name"+topicName);
      const userId = snapshot.val().userId;
      return admin.database().ref("groups/"+groupId+ "/").once("value").
          then((snapshot2)=>{
           
                        return admin.messaging().sendToTopic(
                            topicName, {
                              notification: {
                                title:
                                  ": New chat message",
                                body: name +":"+snapshot.val().message,
                                clickAction: "FLUTTER_NOTIFICATION_CLICK",
                              },
                            });
    });
    

    In my AppDelegate.swift

    import UIKit
    import Flutter
    import Firebase
    import FirebaseMessaging
    
    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
      override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: 
     [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        FirebaseApp.configure()
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: 
      launchOptions)
      }
      override func application(_ application: UIApplication, 
      didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    
       Messaging.messaging().apnsToken = deviceToken
       super.application(application, 
       didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
     }
    }
    

    In my Info.plist

        <key>FirebaseAppDelegateProxyEnabled</key>
    <string>NO</string>
    <key>UIBackgroundModes</key>
    <array>
        <string>fetch</string>
        <string>remote-notification</string>
    </array>
    

    Also make sure that the app registered in the firebase console matches the bundle identifier used in Xcode.