Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter FCM 7 on iOS 14

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+

XCode Settings

enter image description here

AppDelegate.swift

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;       } }  

Info.plist

    <key>FirebaseAppDelegateProxyEnabled</key>     <false/>     <key>FirebaseScreenReportingEnabled</key>     <true/> 

Message Example (Callable function)

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"};     }); 

Flutter Message Service

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),     );   } } 

Call on widget

final FirebaseMessagingService _fcm = FirebaseMessagingService();    @override   void afterFirstLayout(BuildContext context) {     _fcm.initialise();   }  

Only after all these steps, my FCM work correctly.

like image 516
Mayvas Avatar asked Oct 02 '20 13:10

Mayvas


People also ask

Does FCM work on iOS?

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.

Does FCM token change iOS?

"The registration token may change when: The app is restored on a new device. The user uninstalls/reinstall the app.

Is GCM and FCM same?

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.


1 Answers

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'],     }; 
like image 185
Gbenga B Ayannuga Avatar answered Oct 05 '22 19:10

Gbenga B Ayannuga