Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 [FIREBASE_MESSAGING] iOS: message callbacks do not fire when push notification is sent via APNS token #4300

Closed
aytunch opened this issue Dec 2, 2020 · 26 comments
Labels
plugin: messaging type: bug Something isn't working

Comments

@aytunch
Copy link

aytunch commented Dec 2, 2020

Bug report

Describe the bug
On iOS devices,
I upgraded to Firebase Messaging v8.0.0-dev.9
With it, I was able to use getAPNSToken() and successfully send this 64bit hexadecimal to a third party chat service.
When I send a push notification from the third party chat service console and app is on the background, iOS shows the notification banner.
My code looks like this:

      Future<void> func(message) async => print("got message in background");
      .....
      .....
      FirebaseMessaging.onMessage.listen((message) {
          print("message received");
      });
      FirebaseMessaging.onBackgroundMessage(func);
      FirebaseMessaging.onMessageOpenedApp.listen((message) {
          print("opened message");
      });

The onMessageOpenedApp and onBackgroundMessage functions do not get triggered when a notification is sent through the third party chat service while the app is in the background.
However onMessageOpenedApp triggers when I send a message from Firebase Cloud Messaging. Note that onBackgroundMessage does not fire even with Firebase Cloud Messaging.

Also the onMessage function does not get triggered when a notification is sent through the third party chat service while the app is in the foreground.

Steps to reproduce

Steps to reproduce the behavior:

  1. use getAPNSToken() to get the native token for iOS.
  2. send this APNS token to the third party chat service.
  3. send a notification from the third party chat service
  4. take the app to the background
  5. observe that the notification banner is received successfully while onBackgroundMessage is not being triggered.
  6. take the app to the foreground
  7. send a notification from the third party chat service
  8. onMessage is not triggered and the notification is totally omitted by Firebase Messaging

Expected behavior

We should receive the notifications send to our app thorugh onMessage and onBackgroundMessage no matter if they are sent using APNS or FCM token.


Additional context

Add any other context about the problem here.


Flutter doctor

Run flutter doctor and paste the output below:

Click To Expand
[✓] Flutter (Channel stable, 1.22.4, on macOS 11.0.1 20B29 darwin-x64, locale en-TR)
    • Flutter version 1.22.4 at /Users/berat/Documents/Development/flutter
    • Framework revision 1aafb3a8b9 (3 weeks ago), 2020-11-13 09:59:28 -0800
    • Engine revision 2c956a31c0
    • Dart version 2.10.4

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /Users/berat/Library/Android/sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 12.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.2, Build version 12B45b
    • CocoaPods version 1.10.0

[!] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.51.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.16.0

[✓] Connected device (1 available)
    • Ibrahim Berat’s iPhone (mobile) • 4908a07faafc82e9575c22f23c588d81e74ed3c9 • ios • iOS 14.2

! Doctor found issues in 1 category.


Flutter dependencies

Run flutter pub deps -- --style=compact and paste the output below:

Click To Expand
Dart SDK 2.10.4
Flutter SDK 1.22.4
bare_bones 1.0.0+1

dependencies:
- auto_route 0.6.9 [flutter meta]
- bloc 6.1.0 [meta]
- camera 0.5.8+11 [flutter]
- cloud_firestore 0.14.3+1 [flutter meta quiver firebase_core firebase_core_platform_interface cloud_firestore_platform_interface cloud_firestore_web]
- cloud_functions 0.7.1 [meta flutter firebase_core firebase_core_platform_interface cloud_functions_platform_interface cloud_functions_web]
- connectivity 2.0.2 [flutter meta connectivity_platform_interface connectivity_macos connectivity_for_web]
- connectycube_sdk 1.0.0 [flutter http http_parser crypto package_info uuid intl mime xmpp_stone device_id crossplat_objectid path flutter_webrtc web_socket_channel]
- cupertino_icons 1.0.0
- dartz 0.9.2
- dash_chat 1.1.15 [flutter flutter_parsed_text uuid intl transparent_image]
- firebase_auth 0.18.3+1 [meta firebase_core firebase_core_platform_interface firebase_auth_platform_interface firebase_auth_web flutter]
- firebase_core 0.5.2+1 [firebase_core_platform_interface flutter quiver meta firebase_core_web]
- firebase_messaging 8.0.0-dev.9 [meta flutter firebase_core firebase_core_platform_interface firebase_messaging_platform_interface]
- firebase_storage 5.1.0 [flutter firebase_core firebase_core_platform_interface firebase_storage_web firebase_storage_platform_interface quiver]
- flushbar 1.10.4 [flutter]
- flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine]
- flutter_bloc 6.1.1 [flutter bloc provider]
- flutter_ffmpeg 0.3.0 [flutter]
- flutter_local_notifications 3.0.1+6 [flutter platform flutter_local_notifications_platform_interface timezone]
- flutter_localizations 0.0.0 [flutter intl characters collection meta path typed_data vector_math]
- flutter_signin_button 1.1.0 [flutter font_awesome_flutter]
- freezed 0.12.2 [analyzer build build_config meta source_gen freezed_annotation]
- gallery_saver 2.0.1 [flutter path_provider http path]
- geocoding 1.0.5 [flutter geocoding_platform_interface url_launcher]
- geolocator 6.1.8+1 [flutter geolocator_platform_interface]
- get_it 5.0.1 [async meta]
- google_sign_in 4.5.6 [google_sign_in_platform_interface flutter meta google_sign_in_web]
- injectable 1.0.5 [get_it]
- lamp 0.0.6 [flutter]
- logger 0.9.4
- path 1.8.0-nullsafety.1
- path_provider 1.6.24 [flutter path_provider_platform_interface path_provider_macos path_provider_linux path_provider_windows]
- permission_handler 5.0.1+1 [flutter meta permission_handler_platform_interface]
- rxdart 0.24.1
- screen 0.0.5 [flutter]
- shared_preferences 0.5.12+4 [meta flutter shared_preferences_platform_interface shared_preferences_linux shared_preferences_macos shared_preferences_web shared_preferences_windows]
- sign_in_with_apple 2.5.4 [meta flutter]
- uuid 2.2.2 [crypto convert]
- video_player 1.0.1 [meta video_player_platform_interface video_player_web flutter]

dev dependencies:
- auto_route_generator 0.6.10 [build source_gen analyzer path build_runner auto_route]
- bloc_test 7.1.0 [bloc test meta mockito]
- build_runner 1.10.4 [args async build build_config build_daemon build_resolvers build_runner_core code_builder collection crypto dart_style glob graphs http_multi_server io js logging meta mime path pedantic pool pub_semver pubspec_parse shelf shelf_web_socket stack_trace stream_transform timing watcher web_socket_channel yaml]
- flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data]
- freezed_annotation 0.12.0 [collection json_annotation meta]
- injectable_generator 1.0.6 [build source_gen path glob analyzer injectable collection]
- json_serializable 3.5.0 [analyzer build build_config json_annotation meta path source_gen]
- lint 1.3.0

dependency overrides:
- analyzer 0.40.4 [_fe_analyzer_shared args charcode cli_util collection convert crypto glob meta package_config path pub_semver source_span watcher yaml]

transitive dependencies:
- _fe_analyzer_shared 11.0.0 [meta]
- archive 2.0.13 [crypto args path]
- args 1.6.0
- async 2.5.0-nullsafety.1 [collection]
- boolean_selector 2.1.0-nullsafety.1 [source_span string_scanner]
- build 1.5.0 [analyzer async convert crypto logging meta path glob]
- build_config 0.4.2 [checked_yaml json_annotation meta path pubspec_parse yaml]
- build_daemon 2.1.4 [built_collection built_value http_multi_server logging pedantic path pool shelf shelf_web_socket stream_transform watcher web_socket_channel]
- build_resolvers 1.4.3 [analyzer build crypto graphs logging meta path package_config pool pub_semver]
- build_runner_core 6.0.3 [async build build_config build_resolvers collection convert crypto glob graphs json_annotation logging meta path package_config pedantic pool timing watcher yaml]
- built_collection 4.3.2 [collection quiver]
- built_value 7.1.0 [built_collection collection fixnum quiver]
- characters 1.1.0-nullsafety.3
- charcode 1.2.0-nullsafety.1
- checked_yaml 1.0.2 [json_annotation source_span yaml]
- cli_util 0.2.0 [path]
- clock 1.1.0-nullsafety.1
- cloud_firestore_platform_interface 2.2.0 [flutter meta collection firebase_core plugin_platform_interface]
- cloud_firestore_web 0.2.1+1 [flutter flutter_web_plugins http_parser meta firebase_core firebase_core_web cloud_firestore_platform_interface js]
- cloud_functions_platform_interface 3.0.2 [flutter meta firebase_core plugin_platform_interface]
- cloud_functions_web 3.1.0 [firebase_core firebase_core_web cloud_functions_platform_interface flutter flutter_web_plugins http_parser meta js]
- code_builder 3.5.0 [built_collection built_value collection matcher meta]
- collection 1.15.0-nullsafety.3
- connectivity_for_web 0.3.1+4 [connectivity_platform_interface flutter_web_plugins flutter]
- connectivity_macos 0.1.0+7 [flutter]
- connectivity_platform_interface 1.0.6 [flutter meta plugin_platform_interface]
- console 3.1.0 [vector_math]
- convert 2.1.1 [charcode typed_data]
- coverage 0.14.1 [args logging package_config path source_maps stack_trace vm_service]
- crossplat_objectid 2.1.4
- crypto 2.1.5 [collection convert typed_data]
- cryptoutils 0.4.0 [collection]
- dart_style 1.3.9 [analyzer args path source_span]
- device_id 0.2.0 [flutter]
- fake_async 1.2.0-nullsafety.1 [clock collection]
- ffi 0.1.3
- file 5.2.1 [intl meta path]
- firebase_auth_platform_interface 2.1.3 [flutter meta firebase_core plugin_platform_interface]
- firebase_auth_web 0.3.2+1 [flutter flutter_web_plugins meta http_parser intl firebase_core firebase_core_web firebase_auth_platform_interface js]
- firebase_core_platform_interface 2.1.0 [flutter meta plugin_platform_interface quiver]
- firebase_core_web 0.2.1+1 [firebase_core_platform_interface flutter flutter_web_plugins meta js]
- firebase_messaging_platform_interface 1.0.0-dev.6 [flutter meta firebase_core plugin_platform_interface]
- firebase_storage_platform_interface 1.0.1 [flutter meta collection firebase_core plugin_platform_interface]
- firebase_storage_web 0.1.1 [async crypto firebase_core firebase_core_web firebase_storage_platform_interface flutter flutter_web_plugins http js meta]
- fixnum 0.10.11
- flutter_local_notifications_platform_interface 2.0.0+1 [flutter plugin_platform_interface]
- flutter_parsed_text 1.2.5 [flutter]
- flutter_web_plugins 0.0.0 [flutter characters collection meta typed_data vector_math]
- flutter_webrtc 0.4.0 [flutter]
- font_awesome_flutter 8.10.0 [flutter]
- geocoding_platform_interface 1.0.1+1 [flutter meta plugin_platform_interface]
- geolocator_platform_interface 1.0.8 [flutter meta plugin_platform_interface vector_math]
- glob 1.2.0 [async collection node_io path pedantic string_scanner]
- google_sign_in_platform_interface 1.1.2 [flutter meta quiver]
- google_sign_in_web 0.9.2 [google_sign_in_platform_interface flutter flutter_web_plugins meta js]
- graphs 0.2.0
- http 0.12.2 [http_parser path pedantic]
- http_multi_server 2.2.0 [async]
- http_parser 3.1.4 [charcode collection source_span string_scanner typed_data]
- image 2.1.19 [archive xml meta]
- intl 0.16.1 [path]
- io 0.3.4 [charcode meta path string_scanner]
- js 0.6.3-nullsafety.1
- json_annotation 3.1.0
- logging 0.11.4
- matcher 0.12.10-nullsafety.1 [stack_trace]
- meta 1.3.0-nullsafety.3
- mime 0.9.7
- mockito 4.1.3 [analyzer build code_builder collection dart_style matcher meta source_gen test_api]
- nested 0.0.4 [flutter]
- node_interop 1.1.1 [js]
- node_io 1.1.1 [node_interop path]
- node_preamble 1.4.12
- package_config 1.9.3 [path charcode]
- package_info 0.4.3+2 [flutter]
- path_provider_linux 0.0.1+2 [path xdg_directories path_provider_platform_interface flutter]
- path_provider_macos 0.0.4+4 [flutter]
- path_provider_platform_interface 1.0.3 [flutter meta platform plugin_platform_interface]
- path_provider_windows 0.0.4+1 [path_provider_platform_interface meta path flutter ffi win32]
- pedantic 1.10.0-nullsafety.1
- permission_handler_platform_interface 2.0.1 [flutter meta plugin_platform_interface]
- petitparser 3.1.0 [meta]
- platform 2.2.1
- plugin_platform_interface 1.0.3 [meta]
- pool 1.5.0-nullsafety.1 [async stack_trace]
- process 3.0.13 [file intl meta path platform]
- provider 4.3.2+2 [flutter nested collection]
- pub_semver 1.4.4 [collection]
- pubspec_parse 0.1.5 [checked_yaml json_annotation pub_semver yaml]
- quiver 2.1.3 [matcher meta]
- shared_preferences_linux 0.0.2+4 [file flutter meta path path_provider_linux shared_preferences_platform_interface]
- shared_preferences_macos 0.0.1+11 [shared_preferences_platform_interface flutter]
- shared_preferences_platform_interface 1.0.4 [meta flutter]
- shared_preferences_web 0.1.2+7 [shared_preferences_platform_interface flutter flutter_web_plugins meta]
- shared_preferences_windows 0.0.1+3 [shared_preferences_platform_interface flutter ffi file meta path path_provider_platform_interface path_provider_windows]
- shelf 0.7.9 [async collection http_parser path stack_trace stream_channel]
- shelf_packages_handler 2.0.0 [path shelf shelf_static]
- shelf_static 0.2.8 [convert http_parser mime path shelf]
- shelf_web_socket 0.2.3 [shelf web_socket_channel stream_channel]
- sky_engine 0.0.99
- source_gen 0.9.7+1 [analyzer async build dart_style glob meta path pedantic source_span]
- source_map_stack_trace 2.1.0-nullsafety.2 [path stack_trace source_maps]
- source_maps 0.10.10-nullsafety.1 [source_span]
- source_span 1.8.0-nullsafety.2 [charcode collection path term_glyph]
- stack_trace 1.10.0-nullsafety.1 [path]
- stream_channel 2.1.0-nullsafety.1 [async]
- stream_transform 1.2.0
- string_scanner 1.1.0-nullsafety.1 [charcode source_span]
- synchronized 2.2.0+2
- term_glyph 1.2.0-nullsafety.1
- test 1.16.0-nullsafety.5 [analyzer async boolean_selector coverage http http_multi_server io js node_preamble package_config path pedantic pool shelf shelf_packages_handler shelf_static shelf_web_socket source_span stack_trace stream_channel typed_data web_socket_channel webkit_inspection_protocol yaml test_api test_core]
- test_api 0.2.19-nullsafety.2 [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher]
- test_core 0.3.12-nullsafety.5 [analyzer async args boolean_selector collection coverage glob io meta package_config path pedantic pool source_map_stack_trace source_maps source_span stack_trace stream_channel vm_service yaml matcher test_api]
- timezone 0.5.9 [path]
- timing 0.1.1+2 [json_annotation]
- transparent_image 1.0.0
- tuple 1.0.3 [quiver]
- typed_data 1.3.0-nullsafety.3 [collection]
- unorm_dart 0.1.2
- url_launcher 5.7.10 [flutter url_launcher_platform_interface url_launcher_web url_launcher_linux url_launcher_macos url_launcher_windows]
- url_launcher_linux 0.0.1+4 [flutter]
- url_launcher_macos 0.0.1+9 [flutter]
- url_launcher_platform_interface 1.0.9 [flutter meta plugin_platform_interface]
- url_launcher_web 0.1.5+1 [url_launcher_platform_interface flutter flutter_web_plugins meta]
- url_launcher_windows 0.0.1+3 [flutter]
- vector_math 2.1.0-nullsafety.3
- video_player_platform_interface 2.2.0 [flutter meta]
- video_player_web 0.1.4 [flutter flutter_web_plugins meta video_player_platform_interface]
- vm_service 5.2.0 [meta]
- watcher 0.9.7+15 [async path pedantic]
- web_socket_channel 1.1.0 [async crypto stream_channel]
- webkit_inspection_protocol 0.7.3 [logging]
- win32 1.7.3 [ffi]
- xdg_directories 0.1.2 [meta path process]
- xml 4.5.1 [collection convert meta petitparser]
- xmpp_stone 0.3.1 [xml cryptoutils crypto synchronized tuple unorm_dart image quiver console intl]
- yaml 2.2.1 [charcode collection string_scanner source_span]


@aytunch aytunch added Needs Attention This issue needs maintainer attention. type: bug Something isn't working labels Dec 2, 2020
@markusaksli-nc
Copy link
Contributor

markusaksli-nc commented Dec 3, 2020

Hi @aytunch
On iOS you would need to add "content_available": true, to the message payload to temporarily wake the app and trigger a background message callback.
Are you including this in your payload?
Thank you

@markusaksli-nc markusaksli-nc added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Dec 3, 2020
@aytunch
Copy link
Author

aytunch commented Dec 3, 2020

@markusaksli-nc from the console of the chat service I check the content_available flag but nothing changes.
E710FE24-7F55-4266-9646-365C2273C95A

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Dec 3, 2020
@markusaksli-nc
Copy link
Contributor

Does the background callback work if you send a notification through FCM?

Such as

{
  "notification":{
    "title": "This is the title",
    "body": "This is the body",
  },
  "content_available": true,
  "priority": "high",
  "data": {
    "id": 15,
    "type": "comment"
  },
  "to": "FCM token"
}

@markusaksli-nc markusaksli-nc added blocked: customer-response Waiting for customer response, e.g. more information was requested. and removed Needs Attention This issue needs maintainer attention. labels Dec 3, 2020
@aytunch
Copy link
Author

aytunch commented Dec 3, 2020

@markusaksli-nc Hi again:)

I made several tests and below are the summary of the situation:

When the client iOS app is on background, no matter what the content-available is set to, we only see the notification banner. onBackgroundMessage is never triggered. This is same with both FCM and 3rd party chat service(using APNS token)

When the client iOS app is on foreground;
Push notification through FCM console triggers onMessage
But 3rd party chat service APNS console does not trigger onMessage

image (1)

@google-oss-bot google-oss-bot added Needs Attention This issue needs maintainer attention. and removed blocked: customer-response Waiting for customer response, e.g. more information was requested. labels Dec 3, 2020
@markusaksli-nc
Copy link
Contributor

markusaksli-nc commented Dec 4, 2020

My suspicion is that in this case contentAvailable is not being set correctly. In this case, it will seem like it is doing nothing.

The payload you sent seems to be meant for Firebase Admin SDK for Node.js. The FCM HTTP ref describes the property content_available as:

content_available | Optional, boolean | On iOS, use this field to represent content-available in the APNs payload.

The payload that I commented is what works for me when sending background messages.

curl https://fcm.googleapis.com/fcm/send -H "Content-Type:application/json" -X POST -d @send.json -H "Authorization: key=<Cloud Messaging key>"

With this it should at least work through FCM, however, I'm not sure how the third-party notification payload is handled so I can't offer any advice there.

@markusaksli-nc markusaksli-nc added plugin: messaging and removed Needs Attention This issue needs maintainer attention. labels Dec 4, 2020
@iberatkaya
Copy link

I also have a similar issue. I apologize if this is already mentioned if the documentation and maybe I have missed it, but do onMessage and onBackgroundMessage not get triggered when a message is sent with APNS, and does onBackgroundMessage not work with iOS? I have no issues on Android but on iOS onMessage does not get triggered when an APNS message is sent via the Admin SDK, and onBackgroundMessage does not get triggered at all with both APNS or FCM.

@ifanger
Copy link

ifanger commented Dec 8, 2020

I'm facing the same issue on iOS.
Android is working fine with both onMessage and onBackgroundMessage.
iOS isn't triggering onMessage or onBackgroundMessage when the app is terminated.

(when the app is in background or foreground it's working fine)

@acoutts
Copy link

acoutts commented Dec 21, 2020

I thought this plugin only handles messages if they contains the gcm.message_id field, indicating they're sent from FCM?

@aytunch
Copy link
Author

aytunch commented Dec 21, 2020

@acoutts Is there a Flutter package owned/maintained by Google for handling Push Notifications? I would be more than happy to use that one if it exists and works with any provider including Firebase. When I search pub.dev for push notification, the top results are firebase_messaging, awesome_notifications, flutter_apns, apns_flutter. And since I use Firebase backend along with other 3rd party servers which require push notification integration, I need to handle all the messages coming from all the servers. I don't know why Firebase team chose to make their push service propriety by converting APNS tokens to FCM(most probably to make it harder for developers to migrate to another service provider). This might be a good commercial design for Firebase.

However this is not a good design choice for Flutter and for us devs. Push notifications, imho are very essential for an app. And being forced to use multiple push notification packages which basically do the exact same thing(listening to a platform channel and getting a string from the OS) is an overkill. Also, these multiple similar packages usually have conflicts with each other and it is nearly impossible to maintain both when one has a breaking change.

Right now, we are trying to build an app which we are working very hard on. We have a goal, even if the app is not successful, at least it will be able to showcase what Flutter is capable of. We had to face some hurdles about Video and Camera packages but now they are in a more stable condition. For push notifications, I can not say the same. Image in iOS still is not working. Documentation lacks a lot. And this fcm/apns token and being forced to use multiple push packages stalls us big time. Most of the big apps would need to talk to multiple push notification providers. I hope you guys can make things easier for your fellow devs.

@zen-pao
Copy link

zen-pao commented Jan 14, 2021

Wanted to bump this. I'm experiencing the same exact issues as @aytunch using Firebase Messaging v8.0.0-dev.14 where none of the handlers are being called when app is in the foreground. I have also confirmed that push notifications send properly via Firebase Cloud Messaging.

The docs mention for iOS to add

    await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
       alert: true, // Required to display a heads up notification
       badge: true,
       sound: true,
    );

This only actually allows notifications to appear when the app is in the background/terminated. However, when I tap the notification, the callbacks are not called appropriately. Can someone confirm that these handlers are supposed to be called on iOS the same way as on Android?

Additionally, the content-available flag does not seem to make a difference here especially for alert messages.

@icodeyou
Copy link

Any update about this ?

@aytunch
Copy link
Author

aytunch commented Jul 10, 2021

@paod634 could you find a solution to this?
in iOS, the OS shows the APNS notification when in background and terminated but if we click on the notification alert, there is no way to catch them on app opened events.
So at the moment our users can only interact with Firebase push notifications but not 3rd party chat service notifications. I can not take them to the chat page when a chat message is pressed.

@paresy
Copy link

paresy commented Sep 10, 2021

The issue only applies to usage without Firebase because a special field, that is checked, is missing.

You have two options:
a) add the missing field gcm.message_id to your APNS payload and onMessage will be called again
b) patch the library and remove the two checks here:
https://github.com/FirebaseExtended/flutterfire/blob/76e90104e14c6d31bd6edb3aef2a754f2351990b/packages/firebase_messaging/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m#L285
https://github.com/FirebaseExtended/flutterfire/blob/76e90104e14c6d31bd6edb3aef2a754f2351990b/packages/firebase_messaging/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m#L328

If you remove the if's then the onMessage function will also be called again.

There are similar checks on the Android side, but it seems that Google is always adding a corresponding message_id and therefore everything is fine. See: https://github.com/FirebaseExtended/flutterfire/blob/ae683e5251673d089af7ff1c8d55db8724267901/packages/firebase_messaging/firebase_messaging/android/src/main/java/io/flutter/plugins/firebase/messaging/FlutterFirebaseMessagingPlugin.java#L242

I don't know why those checks were implemented on the iOS side, but it is definitely inconsistent that Android works out-of-the-box but iOS requires some "special" treatment.

Maybe someone wants to make a PR which removes those if's and see if it gets merged.
For my part i was able to pull option a) and not require modifications to the package.

@BastienNOEL: Thanks for getting to the bottom of this!

@aytunch
Copy link
Author

aytunch commented Sep 10, 2021

@paresy @BastienNOEL this is great investigation.
Thank you for the detailed info. I think removing these unnecessary checks from the plugin will help out a lot of developers.

What value should we set for gcm.message_id if we go for option a? something unique like a chatMessageId? would it break anything @paresy?

As for option a, it seems it is hard to do because our 3rd party chat service sends them automatically without us having a chance to change the notification data object. So we are stuck with option b.

@markusaksli-nc @Salakar is there a specific reason why iOS and Android behaves differently with gcm.message_id?
Can we please push these changes in to the plugin instead of altering the plugin locally? At the moment our iOS production app lacks a lot of usability because of this bug. We can not take the users to the corresponding chat detail pages when opened the app by push notifications.

@paresy
Copy link

paresy commented Sep 10, 2021

We are just sending a static dummy value so the expression evaluates to true. As far as i have seen there is no further usage for the massage_id besides the existence verification.

@Logixwebtech
Copy link

We are facing same issue, even foreground notification is working fine only in debug mode. Background never work in any mode.
Please help me to fix it, thanks in advance.

@tungthanh0316
Copy link

I have the same issue, How did you resolve that? @aytunch . Could you tell me ? Thanks

@aytunch
Copy link
Author

aytunch commented Apr 29, 2022

@tungthanhcmc unfortunately they still haven't solved this issue. We are thinking of migrating to another BE solution. Reliable Push notifications is a must for a production app. Not being able to catch instances when a customer presses a PN is not acceptable.

@tungthanh0316
Copy link

So sad. Did you try to edit native code? @aytunch

@tek08
Copy link

tek08 commented May 4, 2022

My experience is probably outdated by a year or more at this point, but I ended up digging around in native code + other people's plugins (for months...really), cobbling together a solution that worked specifically for my coding style / project (really, it was rejected for merge into Firebase codebase, but it did work for my needs 😅). I recommend, unfortunately, to anyone having trouble, to do the same / get your hands dirty with some Xcode debugging and/or strategically placed log statements (remote phone-to-server logging, if you have to, as say when debugging opening notifications from terminated state). Worst case, you'll learn a ton about how iOS + Android handle incoming notifications.

I used a combo of my own forks of FlutterFire and AwesomeNotifications on Flutter side, for which my admittedly messily forked repos / commits / PRs are at:

  1. https://github.com/tek08/flutterfire/pulls?q=is%3Apr+author%3Atek08

a. Fixes an issue where tapping on an iOS notification from terminated state would fail, though fwiw, not sure it's perfectly fixed...
b. Adds a new MethodChannel call shouldShowNotification, which asks Flutter if a particular notification should be shown by iOS once it's come in.

  1. https://github.com/tek08/awesome_notifications/pulls?q=is%3Apr+is%3Aclosed

A lot of the trouble folks have with push notifications in flutter/iOS is with delegate chaining. You may have multiple plugins all fighting to be the NotificationCenter's delegate, and then selfishly not forwarding on requests to anyone who had previously claimed delegate. I love AwesomeNotifications, for being able to create notifications on device in response to invisible but reliable DataMessages etc. but it was fairly greedy in terms of wanting to be delegate on iOS, so iirc, I stripped it of such power, and let FlutterFire run the show for handling inbound messages.

On backend (Python FastAPI), I used FirebaseAdmin, with a custom built series of Message objects (DataMessages + NotificationMessages, from which a number of other custom notifications inherited) that are translated into differently (likely mis)configured firebase_admin.messaging.Message objects depending on whether they are to successfully make it to an Android or iOS device, each with a json payload with info about the specific notification type, intercepted by FlutterFire in dart, and then sent to individual handlers/interpreters on Flutter-side, depending on what type of notification subclass they are (as detected from the payload).

TL;DR -- Push notifications was one of the most convoluted features to work with in Flutter for me. I feel your pain. It took me months to get something working somewhat reliably. If I can help at least point you in the right direction, lemme know, though my knowledge at this point is probably wicked out of date if not buried underneath cobwebs in my brain.

Shameless plug: If anyone is looking to help breathe life back into a Flutter / Python (FastAPI + SQLAlchemy + Pulumi) project, and likes the idea of hacking on real estate data either for fun or for the greater good (let's make buying a home / renting an apartment easier, cheaper and more fair for buyers/tenants and sellers/landlords around the world), hit me up (hello@housewren.app). Would love to chat.

@unexus
Copy link

unexus commented Aug 18, 2022

Problem still exists. Still no "onMessage"-callback if app is active and "alert" is present in "aps".
("gcm.message_id" is available)

Checked line 490 in the file:
https://github.com/firebase/flutterfire/blob/master/packages/firebase_messaging/firebase_messaging/ios/Classes/FLTFirebaseMessagingPlugin.m#L490
// If "alert" (i.e. notification) is present in userInfo, this will be called by the other
// "Messaging#onMessage" channel handler
if (userInfo[@"aps"] != nil && userInfo[@"aps"][@"alert"] == nil)

As a quick fix I removed the condition: && userInfo[@"aps"][@"alert"] == nil. Now it works, but I'm not really comfortable with this solution because of the other mentioned "channel handler" in the line comment (could not find it...). Does anyone have a better idea?

@Lyokone
Copy link
Contributor

Lyokone commented Sep 9, 2022

@russellwheatley Do you know why this condition is here?

@russellwheatley
Copy link
Member

@Lyokone The gcm.message_id allows us to interpret which notification is from a Firebase service (console or Firebase admin SDK). We only support messages sent by a Firebase service.

@aytunch
Copy link
Author

aytunch commented Sep 19, 2022

@russellwheatley please correct me if I am misunderstanding something here

We only support messages sent by a Firebase service.

What is the reason for this? Our apps can receive push notifications from multiple sources. And why can we not rely on firebase_messaging plugin to handle all these different sources?

It seems like gcm.message_id not being present causes terminated and background cases to not fire callbacks for 3rd party sources.

In our app, we use Firebase + 3rd party chat service. And in our Flutter app we want to use this plugin to catch all the notifications in a central place and move the app accordingly.

For my current understanding; gcm.message_id checking does not benefit the developers. This causes so much trouble to all of use as you can see from many issues opened up in Flutter fire which are still open after 2+ years.

I want to request you guys to reconsider the gcm.message_id checking again. Please do not omit the callbacks even if gcm.message_id is not present in the payload in this plugin.

@russellwheatley
Copy link
Member

Hello everyone, we’ve reviewed the issues opened for iOS background messages and we want to make our position clear.

Android and iOS handle background messaging differently. The decision made by the iOS operating system whether messages reaches the relevant iOS event handler (and subsequently received by the Dart background messaging handler) is based on a number of criteria, such as: CPU usage, priority level (data-only messages are considered “low priority” by iOS, android does not), battery level, amount of messages being received by the app, background/terminated application state, etc. This is a fundamental difference between the platforms, and you need to be aware of them when designing your application.

One solution suggested for iOS data-only messages unreliability has been to add a NotificationExtension. But this will still not create parity with Android as you will still have to include a notification with your message (therefore not data-only). It will still render the original notification if you do not update/mutate the notification that comes through the system in a timely manner. We are not currently considering this as a solution due to these limitations.

We also will not support non-FCM messages from third party packages. We specifically only support messages received from the Firebase APIs since we cannot guarantee that messages received from third party packages will not have any unintended side-effects on other Firebase products such as messaging delivery reporting and Analytics data.

To help us triage and locate genuine issues that need to be addressed we have created a specific issue template for iOS background messages. If you believe you still have an issue that needs to be addressed, please create a new issue following this template.

I will be closing this issue in favor of raising a new issue with the new template above. This template will help you provide us with all the information we need to investigate a potential issue with background messaging on iOS.

@aytunch
Copy link
Author

aytunch commented Sep 27, 2022

We also will not support non-FCM messages from third party packages. We specifically only support messages received from the Firebase APIs since we cannot guarantee that messages received from third party packages will not have any unintended side-effects on other Firebase products such as messaging delivery reporting and Analytics data.

@russellwheatley Then may I ask why does firebase_messaging catches 3rd party notifications when the app is in the foreground? This is not a consistent behavior. Do the "side-effects" you mention above not happen when app is in the foreground? If we knew this was the case from the beginning, we would reconsider choosing Firebase as a backend or reconsider our 3rd party services.

If 3rd party notifications are received by onMessage callback but not with terminated and background callbacks, this is greatly misleading to us developers.

@firebase firebase locked and limited conversation to collaborators Oct 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
plugin: messaging type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests