Firebase FCM notification received in iOS simulator but as GCM(?) on real iOS device in flutter app

3,537

Solution 1

According to Firebase support, we should not be able to get push notifications in the simulator, and they say that the gcm-format above is indeed the correct one.

The solution is to always use key-value pairs as stated in the answer to this previous question FCM - Get Message Label

Solution 2

For those who still struggle with this, there seems an alternative solution. While the structure of the data can be different in various conditions (iOS/Android or Real device/Simulator), the key names of those essential parts of the data are considered to be unique no matter how deeply nested: "title" and "body". Therefore, extracting the values of those 'title' and 'body' entries might solve the problem.

//get title value from the message load (whether data or push)
String _title = _findFirstKeyValue(message, 'title');

The following is a recursive function to get the first matching entry from the message Map.

  String _findFirstKeyValue(Map data, String targetKey) {
    for (final k in data.keys) {
      final v = data[k];

      if (v is Map) { // go deeper if the value is still a kind of Map
        final String _temp = _findFirstKeyValue(v, targetKey);
        if (_temp != '') return _temp;

      } else { // when the value is primitive Key-Value pair
        if (k.toString().toLowerCase() == targetKey.toLowerCase())  {
          return v.toString();
        }
      }
    }
    return '';
  }

Note that return will not be fired if you use data.forEach rather than ordinary for loop.

Share:
3,537
Jonas357
Author by

Jonas357

Doing innovative stuff leads to programming in all different kinds of languages.

Updated on December 13, 2022

Comments

  • Jonas357
    Jonas357 over 1 year

    edit: it is supposed to look like it does on the device log, according to Firebase support

    I am adding push notifications via FCM to my Flutter app, but the message format is very different on the iOS Simulator vs. my iPhone 5s. When receiving a push notification from the Firebase console to an active/opened app.

    Problem: What do I need to do to make sure the real device receives the message in the correct format?


    Log from Simulator (iPhone XR, 12.2) (looks like in the official code examples):

        onMessage: {
        from: 123000000000,
        collapse_key: com.mydomainnamehere,
        notification: {
            body: Lorem ipsum,
            title: Title,
            e: 1,
            tag: campaign_collapse_key_9876543210011223344
        }
    }
    


    Log from real device (iPhone 5s, 12.2) (can't find any references online to this):

    onMessage: {
        google.c.a.c_l: notif_name,
        google.c.a.e: 1,
        aps: {
            alert: {
                title: Title,
                body: Lorem ipsum
            }
        },
        gcm.n.e: 1,
        google.c.a.c_id: 9876543210011223344,
        google.c.a.udt: 0,
        gcm.message_id: 1234567800998877,
        google.c.a.ts: 1234567800
    }
    



    The notification is sent from the Firebase console to all devices, the logs are taken from the same notification (but I anonymized the id's).

    The Device and Simulator is running the same Flutter code from Android Studio, at the same time.

    Parts of my pubspec.yaml that refers to FCM

      firebase_core: ^0.4.0+1
      firebase_auth: 0.11.1
      cloud_firestore: ^0.11.0+2
      firestore_ui: ^1.4.0
      firebase_messaging: ^5.0.2
    

    Software and SDK Versions

    Flutter Channel dev, v1.8.4, Mac OS X 10.14.5, Android SDK version 28.0.3, Xcode 10.2.1, Android Studio version 3.4

    Flutter message-handling code

    void initState() {
        super.initState();
    
        if (Platform.isIOS) {
          iosSubscription = _fcm.onIosSettingsRegistered.listen((IosNotificationSettings settings) {
            print("FCM settings received: $settings");
          });
    
          _fcm.requestNotificationPermissions(IosNotificationSettings());
        }
    
        _fcm.configure(
          onMessage: (Map<String, dynamic> message) async {
            print("onMessage: $message");
          },
        );
    
        getFcmToken();
      }
    
      void getFcmToken() async {
        var token = await FirebaseMessaging().getToken();
        print("Token $token");
      }
    

    I was expecting that the JSON format would be the same on both the simulator and a real device. But the real device isn't even receiving all of the notification.