Skip to content

Document how to extract message body using firebase_messaging #28196

@kbrmimbyl

Description

@kbrmimbyl

There's some confusion w.r.t. whether onLaunch, onResume and onMessage are getting called on iOS or not. Many people are still complaining that one or more of these are not getting called (for e.g. see #18425).

How to reproduce?

Add firebase_messaging to your flutter project, configure for both iOS and Android as explained in the plugin's README. Then send a notification each to your iOS and Android apps using Firebase Console> Cloud Messaging by setting only the "Notification Text" in Step 1 (this is the only mandatory field in this step). Remember to set click_action to FLUTTER_NOTIFICATION_CLICK under Additional Options (optional, Step 5). In your flutter project, try to extract what you put in as "Notification Text" above using the following dart code to configure FirebaseMessaging:

onMessage: (Map<String, dynamic> msg) {
  _message = msg['notification']['body'];
  print(_message);
},
onResume: (Map<String, dynamic> msg) {
  _message = msg['notification']['body'];
  print(_message);
},
onLaunch: (Map<String, dynamic> msg) {
  _message = msg['notification']['body'];
  print(_message);
},

Result

All three messages are printed for Android. To be more clear, onMessage gets executed when the app is in the foreground when it gets a notification, onResume when the app is running in the background and you tap on the notification, onLaunch when the app isn't running and you tap on the notification. But on iOS, none of the print statements are executed. The notifications do arrive when the app is not in the foreground, but nothing happens when you click on them. No print outputs in XCode or VSCode. This leads to the idea that none of the three functions are getting called on iOS.

How I solved it

On looking more closely, I found out that all three functions are actually getting called. Only, execution was apparently getting stopped at _message = msg['notification']['body'];, so the print never got called on iOS. Flutter doesn't log any complaints either.

The issue is, the path to the "Notification Text" is different on iOS and Android, so I ended up using this code:

onMessage: (Map<String, dynamic> msg) {
  if (Theme.of(context).platform == TargetPlatform.iOS)
      _message = msg['aps']['alert'];
  else
      _message = msg['notification']['body'];
  print(_message);
},
onResume: (Map<String, dynamic> msg) {
  if (Theme.of(context).platform == TargetPlatform.iOS)
      _message = msg['aps']['alert'];
  else
      _message = msg['notification']['body'];
  print(_message);
},
onLaunch: (Map<String, dynamic> msg) {
  if (Theme.of(context).platform == TargetPlatform.iOS)
      _message = msg['aps']['alert'];
  else
      _message = msg['notification']['body'];
  print(_message);
},

Now everything works on both iOS and Android.

How this problem can be prevented

Going further, I request the Flutter/Firebase team to document how msg looks on iOS and Android. The firebase_messaging plugin's README is a good place. Also, why isn't Flutter throwing any error when it can't access msg['notification']['body'] on iOS?

Note

#23148 is somewhat different... that one is about keeping the structure of msg the same across onLaunch, onResume and onMessage. I actually find them to be the same! The issue I'm raising here is that it's not clear what the structures on Android and iOS are. It's desirable for the structures to be the same, but it's not as important as knowing what they are

Metadata

Metadata

Assignees

No one assigned

    Labels

    p: firebaseFirebase pluginsp: firebase_messagingThe Firebase Messaging pluginpackageflutter/packages repository. See also p: labels.platform-iosiOS applications specifically

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions