For everyone who goes crazy from FCM after updating to iOS14 & Xcode12. I spent 2 days resolving the issues. On the simulator, it works but on a real device, it does not. Maybe these instructions can help someone & prevent wasting the time. Also, it would be great to listen to some thoughts from Flutter Guru if all these steps can be improved :).
Notice: Instructions for new FCM versions 9+
import UIKit import Flutter import GoogleMaps import Firebase import FirebaseMessaging @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate } GMSServices.provideAPIKey("") GeneratedPluginRegistrant.register(with: self) application.registerForRemoteNotifications() return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { Auth.auth().setAPNSToken(deviceToken, type: .prod) } override func application(_ application: UIApplication, didReceiveRemoteNotification notification: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { if Auth.auth().canHandleNotification(notification) { completionHandler(.noData) return } } override func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool { if Auth.auth().canHandle(url) { return true } return false; } }
<key>FirebaseAppDelegateProxyEnabled</key> <false/> <key>FirebaseScreenReportingEnabled</key> <true/>
Your message must be sent with these options:
{ mutableContent: true, contentAvailable: true, apnsPushType: "background" }
Just an example to use in callable function
exports.sendNotification = functions.https.onCall( async (data) => { console.log(data, "this sendNotification data"); var userTokens = [USERTOKEN1,USERTOKEN2,USERTOKEN3]; var payload = { notification: { title: '', body: '', image: '', }, data: { type:'', }, }; for (const [userToken,userUID] of Object.entries(userTokens)) { admin.messaging().sendToDevice(userToken, payload, { mutableContent: true, contentAvailable: true, apnsPushType: "background" }); } return {code: 100, message: "notifications send successfully"}; });
import 'dart:io'; import 'package:hive/hive.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:octopoos/providers/app.dart'; Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message) async {} class FirebaseMessagingService { final _app = AppProvider(); var _prefs = Hive.box('preferences'); FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); void initialise() { var android = AndroidInitializationSettings('mipmap/ic_launcher'); var ios = IOSInitializationSettings(); var platform = InitializationSettings(android, ios); _flutterLocalNotificationsPlugin.initialize(platform); _firebaseMessaging.configure( onLaunch: (Map<String, dynamic> message) async { _app.storeNotification(message); }, onResume: (Map<String, dynamic> message) async { _app.storeNotification(message); }, onMessage: (Map<String, dynamic> message) async { _app.storeNotification(message); if (_prefs.get('pushServiceState') == true) _showNotification(message); }, onBackgroundMessage: Platform.isIOS ? null : backgroundMessageHandler, ); if (Platform.isIOS) iOSPermission(); _firebaseMessaging.getToken().then((token) { _prefs.put('fcmToken', token); }); } void iOSPermission() { _firebaseMessaging.requestNotificationPermissions( IosNotificationSettings(sound: true, badge: true, alert: true, provisional: true)); _firebaseMessaging.onIosSettingsRegistered.listen((IosNotificationSettings settings) { print('IOS Setting Registed'); }); } Future<void> _showNotification(Map<String, dynamic> message) async { var android = AndroidNotificationDetails( 'messages', "Octopoos", "channelDescription", ); var iOS = IOSNotificationDetails(); await _flutterLocalNotificationsPlugin.show( 0, message['notification']['title'], message['notification']['body'], NotificationDetails(android, iOS), ); } }
final FirebaseMessagingService _fcm = FirebaseMessagingService(); @override void afterFirstLayout(BuildContext context) { _fcm.initialise(); }
Only after all these steps, my FCM work correctly.
Stay organized with collections Save and categorize content based on your preferences. For Apple client apps, you can receive notification and data payloads up to 4000 bytes over the Firebase Cloud Messaging APNs interface.
"The registration token may change when: The app is restored on a new device. The user uninstalls/reinstall the app.
Firebase Cloud Messaging (FCM), formerly known as Google Cloud Messaging (GCM), is a cross-platform cloud solution for messages and notifications for Android, iOS, and web applications, which as of June 2022 can be used at no cost.
can u try sample payload if it works.
it is stated here
let payload = { notification: { title: 'Match', body: `${user2name} Match with You`, }, data: { key: 'Match', id: user2, body: user2name, click_action: "FLUTTER_NOTIFICATION_CLICK" }, android: { priority: "high", }, 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 }, }, token: deviceTokenuUser1.data()['tokens'], };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With