firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.72k stars 3.97k forks source link

[firebase_messaging]: iOS is not receiving the push notifications with apns-push-type = background #13691

Closed mohsinnaqvi606 closed 1 week ago

mohsinnaqvi606 commented 1 week ago

Is there an existing issue for this?

Which plugins are affected?

Messaging

Which platforms are affected?

iOS

Description

iOS is not receiving the push notifications with apns-push-type = background, it only receives push notifications with the apns-push-type = alert.

Type alert payload

{
    "aps": {
        "alert": {
            "title": "Missed Call",
            "body": "John Doe"
        }
    }
}

Type background payload

{
    "aps": {
        "content-available": 1
    },
    "data": {
        "incomingCall": {
            "caller": {
                "name": "John Doe",
                "number": "1234"
            }
        }
    }
}

Reproducing the issue

Use this payload to send notifications to the IOS.

{ "aps": { "content-available": 1, "sound": "", "badge": 3, "alert": "" }, "data": { "badge": "23", "silent": "false", "stat": "false", "dataId": "f9d2c97d-d4c0-ee11-85f9-6045bd014a58", "unreadTextConversations": "2", "notificationType": "NewTextMessage", "urgent": "urgent", "message": "Secure text from Holby, John R", "value": "f9d2c97d-d4c0-ee11-85f9-6045bd014a58" } } { "aps": { "content-available": 1, "sound": "", "badge": 3, "alert": "" }, "data": { "badge": "23", "silent": "false", "stat": "false", "dataId": "f9d2c97d-d4c0-ee11-85f9-6045bd014a58", "unreadTextConversations": "2", "notificationType": "NewTextMessage", "urgent": "urgent", "message": "Secure text from Holby, John R", "value": "f9d2c97d-d4c0-ee11-85f9-6045bd014a58" } }

Firebase Core version

3.6.0

Flutter Version

3.24.4

Relevant Log Output

I have tried native code on IOS and the App is receiving notifications, but firebase_messaginig is not working with silent/data-only notification.

I used this code, on the native side

   override func application(
          _ application: UIApplication,
          didReceiveRemoteNotification userInfo: [AnyHashable : Any],
          fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
      ) {
          // Process the notification data
          if let dataPayload = userInfo["data"] as? [String: Any] {
              // Handle your background task here
              print(userInfo);
              print("Received background notification with data: \(dataPayload)")
          }

          completionHandler(.newData)
      }

this is output after receiving a notification

[AnyHashable("data"): {
    badge = 23;
    dataId = "f9d2c97d-d4c0-ee11-85f9-6045bd014a58";
    message = "Secure text from Holby, John R";
    notificationType = NewTextMessage;
    silent = false;
    stat = false;
    unreadTextConversations = 2;
    urgent = urgent;
    value = "f9d2c97d-d4c0-ee11-85f9-6045bd014a58";
}, AnyHashable("aps"): {
    alert = "";
    badge = 3;
    "content-available" = 1;
    sound = "";
}]
Received background notification with data: ["value": f9d2c97d-d4c0-ee11-85f9-6045bd014a58, "urgent": urgent, "stat": false, "silent": false, "dataId": f9d2c97d-d4c0-ee11-85f9-6045bd014a58, "message": Secure text from Holby, John R, "notificationType": NewTextMessage, "badge": 23, "unreadTextConversations": 2]

Flutter dependencies

Expand Flutter dependencies snippet
```yaml Dart SDK 3.5.4 Flutter SDK 3.24.4 doctoc 4.0.0+30830 dependencies: - audioplayers 6.1.0 [audioplayers_android audioplayers_darwin audioplayers_linux audioplayers_platform_interface audioplayers_web audioplayers_windows file flutter http meta path_provider synchronized uuid] - avatar_glow 3.0.1 [flutter] - cached_network_image 3.4.1 [cached_network_image_platform_interface cached_network_image_web flutter flutter_cache_manager octo_image] - cupertino_icons 1.0.8 - device_info_plus 11.1.0 [device_info_plus_platform_interface ffi file flutter flutter_web_plugins meta web win32 win32_registry] - easy_sticky_header 1.1.1 [flutter] - file_picker 8.1.3 [flutter flutter_web_plugins flutter_plugin_android_lifecycle plugin_platform_interface ffi path win32 cross_file web] - firebase_analytics 11.3.3 [firebase_analytics_platform_interface firebase_analytics_web firebase_core firebase_core_platform_interface flutter] - firebase_core 3.6.0 [firebase_core_platform_interface firebase_core_web flutter meta] - firebase_crashlytics 4.1.3 [firebase_core firebase_core_platform_interface firebase_crashlytics_platform_interface flutter stack_trace] - firebase_messaging 15.1.3 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta] - flutter 0.0.0 [characters collection material_color_utilities meta vector_math sky_engine] - flutter_cached_pdfview 0.4.3 [flutter flutter_pdfview flutter_cache_manager path_provider path] - flutter_local_notifications 17.2.4 [clock flutter flutter_local_notifications_linux flutter_local_notifications_platform_interface timezone] - flutter_svg 2.0.12 [flutter http vector_graphics vector_graphics_codec vector_graphics_compiler] - flutter_widget_from_html 0.15.2 [flutter flutter_widget_from_html_core fwfh_cached_network_image fwfh_chewie fwfh_just_audio fwfh_svg fwfh_url_launcher fwfh_webview html] - get 4.6.6 [flutter] - get_storage 2.1.1 [flutter get path_provider] - http 1.2.2 [async http_parser meta web] - image_picker 1.1.2 [flutter image_picker_android image_picker_for_web image_picker_ios image_picker_linux image_picker_macos image_picker_platform_interface image_picker_windows] - in_app_update 4.2.3 [flutter] - intl 0.19.0 [clock meta path] - local_auth 2.3.0 [flutter local_auth_android local_auth_darwin local_auth_platform_interface local_auth_windows] - percent_indicator 4.2.3 [flutter] - section_view 2.0.6 [flutter flutter_list_view] - textfield_tags 3.0.1 [flutter] - url_launcher 6.3.1 [flutter url_launcher_android url_launcher_ios url_launcher_linux url_launcher_macos url_launcher_platform_interface url_launcher_web url_launcher_windows] dev dependencies: - flutter_test 0.0.0 [flutter test_api matcher path fake_async clock stack_trace vector_math leak_tracker_flutter_testing async boolean_selector characters collection leak_tracker leak_tracker_testing material_color_utilities meta source_span stream_channel string_scanner term_glyph vm_service] transitive dependencies: - _flutterfire_internals 1.3.44 [collection firebase_core firebase_core_platform_interface flutter meta] - args 2.6.0 - async 2.11.0 [collection meta] - audio_session 0.1.21 [flutter flutter_web_plugins rxdart meta] - audioplayers_android 5.0.0 [audioplayers_platform_interface flutter] - audioplayers_darwin 6.0.0 [audioplayers_platform_interface flutter] - audioplayers_linux 4.0.0 [audioplayers_platform_interface flutter] - audioplayers_platform_interface 7.0.0 [collection flutter meta plugin_platform_interface] - audioplayers_web 5.0.1 [audioplayers_platform_interface flutter flutter_web_plugins web] - audioplayers_windows 4.0.0 [audioplayers_platform_interface flutter] - boolean_selector 2.1.1 [source_span string_scanner] - cached_network_image_platform_interface 4.1.1 [flutter flutter_cache_manager] - cached_network_image_web 1.3.1 [cached_network_image_platform_interface flutter flutter_cache_manager web] - characters 1.3.0 - chewie 1.8.5 [cupertino_icons flutter provider video_player wakelock_plus] - clock 1.1.1 - collection 1.18.0 - cross_file 0.3.4+2 [meta web] - crypto 3.0.6 [typed_data] - csslib 1.0.2 [source_span] - dbus 0.7.10 [args ffi meta xml] - device_info_plus_platform_interface 7.0.1 [flutter meta plugin_platform_interface] - fake_async 1.3.1 [clock collection] - ffi 2.1.3 - file 7.0.1 [meta path] - file_selector_linux 0.9.3 [cross_file file_selector_platform_interface flutter] - file_selector_macos 0.9.4+2 [cross_file file_selector_platform_interface flutter] - file_selector_platform_interface 2.6.2 [cross_file flutter http plugin_platform_interface] - file_selector_windows 0.9.3+3 [cross_file file_selector_platform_interface flutter] - firebase_analytics_platform_interface 4.2.5 [_flutterfire_internals firebase_core flutter meta plugin_platform_interface] - firebase_analytics_web 0.5.10+2 [_flutterfire_internals firebase_analytics_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins] - firebase_core_platform_interface 5.3.0 [collection flutter flutter_test meta plugin_platform_interface] - firebase_core_web 2.18.1 [firebase_core_platform_interface flutter flutter_web_plugins meta web] - firebase_crashlytics_platform_interface 3.6.44 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface] - firebase_messaging_platform_interface 4.5.46 [_flutterfire_internals firebase_core flutter meta plugin_platform_interface] - firebase_messaging_web 3.9.2 [_flutterfire_internals firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins meta web] - fixnum 1.1.1 - flutter_cache_manager 3.4.1 [clock collection file flutter http path path_provider rxdart sqflite uuid] - flutter_list_view 1.1.28 [flutter] - flutter_local_notifications_linux 4.0.1 [dbus ffi flutter flutter_local_notifications_platform_interface path xdg_directories] - flutter_local_notifications_platform_interface 7.2.0 [flutter plugin_platform_interface] - flutter_pdfview 1.3.4 [flutter] - flutter_plugin_android_lifecycle 2.0.23 [flutter] - flutter_web_plugins 0.0.0 [flutter characters collection material_color_utilities meta vector_math] - flutter_widget_from_html_core 0.15.2 [csslib flutter html logging] - fwfh_cached_network_image 0.14.3 [cached_network_image flutter flutter_cache_manager flutter_widget_from_html_core] - fwfh_chewie 0.14.8 [chewie flutter flutter_widget_from_html_core video_player] - fwfh_just_audio 0.15.2 [flutter flutter_widget_from_html_core just_audio] - fwfh_svg 0.8.3 [flutter flutter_svg flutter_widget_from_html_core] - fwfh_url_launcher 0.9.1 [flutter flutter_widget_from_html_core url_launcher] - fwfh_webview 0.15.2 [flutter flutter_widget_from_html_core logging web webview_flutter webview_flutter_android webview_flutter_wkwebview] - html 0.15.5 [csslib source_span] - http_parser 4.0.2 [collection source_span string_scanner typed_data] - image_picker_android 0.8.12+17 [flutter flutter_plugin_android_lifecycle image_picker_platform_interface] - image_picker_for_web 3.0.6 [flutter flutter_web_plugins image_picker_platform_interface mime web] - image_picker_ios 0.8.12+1 [flutter image_picker_platform_interface] - image_picker_linux 0.2.1+1 [file_selector_linux file_selector_platform_interface flutter image_picker_platform_interface] - image_picker_macos 0.2.1+1 [file_selector_macos file_selector_platform_interface flutter image_picker_platform_interface] - image_picker_platform_interface 2.10.0 [cross_file flutter http plugin_platform_interface] - image_picker_windows 0.2.1+1 [file_selector_platform_interface file_selector_windows flutter image_picker_platform_interface] - just_audio 0.9.42 [just_audio_platform_interface just_audio_web audio_session rxdart path path_provider async uuid crypto meta flutter] - just_audio_platform_interface 4.3.0 [flutter plugin_platform_interface] - just_audio_web 0.4.13 [just_audio_platform_interface flutter flutter_web_plugins web] - leak_tracker 10.0.5 [clock collection meta path vm_service] - leak_tracker_flutter_testing 3.0.5 [flutter leak_tracker leak_tracker_testing matcher meta] - leak_tracker_testing 3.0.1 [leak_tracker matcher meta] - local_auth_android 1.0.46 [flutter flutter_plugin_android_lifecycle intl local_auth_platform_interface] - local_auth_darwin 1.4.1 [flutter intl local_auth_platform_interface] - local_auth_platform_interface 1.0.10 [flutter plugin_platform_interface] - local_auth_windows 1.0.11 [flutter local_auth_platform_interface] - logging 1.3.0 - matcher 0.12.16+1 [async meta stack_trace term_glyph test_api] - material_color_utilities 0.11.1 [collection] - meta 1.15.0 - mime 2.0.0 - nested 1.0.0 [flutter] - octo_image 2.1.0 [flutter] - package_info_plus 8.1.0 [ffi flutter flutter_web_plugins http meta path package_info_plus_platform_interface web win32 clock] - package_info_plus_platform_interface 3.0.1 [flutter meta plugin_platform_interface] - path 1.9.0 - path_parsing 1.1.0 [meta vector_math] - path_provider 2.1.5 [flutter path_provider_android path_provider_foundation path_provider_linux path_provider_platform_interface path_provider_windows] - path_provider_android 2.2.12 [flutter path_provider_platform_interface] - path_provider_foundation 2.4.0 [flutter path_provider_platform_interface] - path_provider_linux 2.2.1 [ffi flutter path path_provider_platform_interface xdg_directories] - path_provider_platform_interface 2.1.2 [flutter platform plugin_platform_interface] - path_provider_windows 2.3.0 [ffi flutter path path_provider_platform_interface] - petitparser 6.0.2 [meta] - platform 3.1.6 - plugin_platform_interface 2.1.8 [meta] - provider 6.1.2 [collection flutter nested] - push 2.3.0 [flutter push_platform_interface push_android push_ios push_macos] - push_android 0.6.0 [flutter push_platform_interface] - push_ios 0.5.1 [flutter push_platform_interface] - push_macos 0.0.1 [flutter cupertino_icons] - push_platform_interface 0.6.0 [flutter plugin_platform_interface] - rxdart 0.28.0 - sky_engine 0.0.99 - source_span 1.10.0 [collection path term_glyph] - sprintf 7.0.0 - sqflite 2.4.0 [flutter sqflite_android sqflite_darwin sqflite_platform_interface sqflite_common path] - sqflite_android 2.4.0 [flutter sqflite_common path sqflite_platform_interface] - sqflite_common 2.5.4+5 [synchronized path meta] - sqflite_darwin 2.4.1-1 [flutter sqflite_platform_interface meta sqflite_common path] - sqflite_platform_interface 2.4.0 [flutter platform sqflite_common plugin_platform_interface meta] - stack_trace 1.11.1 [path] - stream_channel 2.1.2 [async] - string_scanner 1.2.0 [source_span] - synchronized 3.3.0+3 - term_glyph 1.2.1 - test_api 0.7.2 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph] - timezone 0.9.4 [path] - typed_data 1.4.0 [collection] - url_launcher_android 6.3.14 [flutter url_launcher_platform_interface] - url_launcher_ios 6.3.1 [flutter url_launcher_platform_interface] - url_launcher_linux 3.2.0 [flutter url_launcher_platform_interface] - url_launcher_macos 3.2.1 [flutter url_launcher_platform_interface] - url_launcher_platform_interface 2.3.2 [flutter plugin_platform_interface] - url_launcher_web 2.3.3 [flutter flutter_web_plugins url_launcher_platform_interface web] - url_launcher_windows 3.1.3 [flutter url_launcher_platform_interface] - uuid 4.5.1 [crypto sprintf meta fixnum] - vector_graphics 1.1.12 [flutter http vector_graphics_codec] - vector_graphics_codec 1.1.12 - vector_graphics_compiler 1.1.12 [args meta path path_parsing vector_graphics_codec xml] - vector_math 2.1.4 - video_player 2.9.2 [flutter html video_player_android video_player_avfoundation video_player_platform_interface video_player_web] - video_player_android 2.7.16 [flutter video_player_platform_interface] - video_player_avfoundation 2.6.2 [flutter video_player_platform_interface] - video_player_platform_interface 6.2.3 [flutter plugin_platform_interface] - video_player_web 2.3.3 [flutter flutter_web_plugins video_player_platform_interface web] - vm_service 14.2.5 - wakelock_plus 1.2.8 [flutter flutter_web_plugins meta wakelock_plus_platform_interface win32 dbus package_info_plus web] - wakelock_plus_platform_interface 1.2.1 [flutter plugin_platform_interface meta] - web 1.1.0 - webview_flutter 4.9.0 [flutter webview_flutter_android webview_flutter_platform_interface webview_flutter_wkwebview] - webview_flutter_android 3.16.9 [flutter webview_flutter_platform_interface] - webview_flutter_platform_interface 2.10.0 [flutter meta plugin_platform_interface] - webview_flutter_wkwebview 3.16.1 [flutter path webview_flutter_platform_interface] - win32 5.8.0 [ffi] - win32_registry 1.1.5 [ffi win32] - xdg_directories 1.1.0 [meta path] - xml 6.5.0 [collection meta petitparser] ```

Additional context and comments

Android it's working perfectly, but IOS is working only for the foreground. On background, nothing happening

russellwheatley commented 1 week ago

@mohsinnaqvi606 - this fix has been merged: https://github.com/firebase/flutterfire/pull/13525

Slated for a release tomorrow 👍

mohsinnaqvi606 commented 1 week ago

@russellwheatley Thanks. I hope everything will work fine.

kangmyonggyu commented 1 week ago

@russellwheatley I have switched latest version, but ios background notification does not working properly on release mode

firebase_messaging: git: url: https://github.com/firebase/flutterfire.git path: packages/firebase_messaging/firebase_messaging ref: main

stam0912 commented 1 week ago

@mohsinnaqvi606 - this fix has been merged: #13525

Slated for a release tomorrow 👍

Hi @russellwheatley ,

The latest release is not compatible with other packages I'm using. I'm not able to upgrade the package. Do you have any work around for
firebase_messaging: ^15.1.0 firebase_core: ^3.4.0

Thank you.

mohsinnaqvi606 commented 3 days ago

The latest version is still not working on IOS. Unable to receive silent notification into the App in any state(Foreground, Background, or Terminated).

Has anyone found a solution?

mohsinnaqvi606 commented 3 days ago

@russellwheatley any update on this? The app is in production and the feature is broken. Please share update/progress on this.

stam0912 commented 2 days ago

The latest version is still not working on IOS. Unable to receive silent notification into the App in any state(Foreground, Background, or Terminated).

Has anyone found a solution?

@mohsinnaqvi606 I ended up implementing a notification service extension to handle the incoming silent notification and show a custom push notification. It seems like it's working even if the app is running in the background.

You can find information here.

I updated my fcm in the following structure:

{ "topic": topicName, "android": { "priority": "high", "data": { "data1": data1, "data2": data2 } } "apns":{ "header": { "apns-priority": "10" }, payload:{ "aps":{ "badge": 1, "sound": yourChoiceOfSound, "vibrate": "true", "content-available": 1, "mutable-content": 1, "alert":{ "title": defaultTitle, "body": defaultBody, } }, "data1": data1, "data2": data2 } } }

I use data only messages because I want to show custom notification. I use awesome_notifications to show custom notification only on Android, and I implement the notification service extension to do the same on iOS.

mohsinnaqvi606 commented 1 day ago

@stam0912 can you share the code?

I need to show custom notifications with custom sounds on the base of the notification type. I also need to navigate on different screens.

Is it all possible by Notification Service Extension ?

mohsinnaqvi606 commented 1 day ago

@russellwheatley please update on this. The main feature of the App is not working, so the App is useless

stam0912 commented 1 day ago

@stam0912 can you share the code?

I need to show custom notifications with custom sounds on the base of the notification type. I also need to navigate on different screens.

Is it all possible by Notification Service Extension ?

@mohsinnaqvi606 Yes I didn't change anything on the flutter side, I just added the notification service extension so that it works on iOS.

NotificationService.swift (You will find this file after adding the extension in Xcode)

`import UserNotifications

class NotificationService: UNNotificationServiceExtension {

var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?

override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

    if let bestAttemptContent = bestAttemptContent {
        // Modify the notification content here...

        // Access UserDefaults in App Group
        let sharedDefaults = UserDefaults(suiteName: "group.com.xxx.xxx")
        let locale = sharedDefaults?.string(forKey: "localeKey") ?? "en"

        bestAttemptContent.title = "\(bestAttemptContent.title)"

        // Load localized messages based on the locale
        if let localizedMessages = loadLocalizedMessages(for: locale) {
            if let type = bestAttemptContent.userInfo["msgType"] as? String, type == "1" {
                let bodyKey = (bestAttemptContent.userInfo["msgBody"] as? String == "1") ? "bodyKey1" : "bodyKey2"
                bestAttemptContent.body = localizedMessages[bodyKey] ?? bestAttemptContent.body
            }else{
                if let bodyValue = bestAttemptContent.userInfo["msgBody"] as? String {
                    let bodyKey: String
                    switch bodyValue {
                    case "0":
                        bodyKey = "bodyKey3"
                    case "1":
                        bodyKey = "bodyKey4"
                    default:
                        bodyKey = "" 
                    }

                    bestAttemptContent.body = localizedMessages[bodyKey] ?? bestAttemptContent.body
                }
            }
        }
        contentHandler(bestAttemptContent)
    }
}

override func serviceExtensionTimeWillExpire() {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
    if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
        contentHandler(bestAttemptContent)
    }
}

func loadLocalizedMessages(for locale: String) -> [String: String]? {
    guard let url = Bundle.main.url(forResource: locale, withExtension: "json") else {
        return nil
    }

    do {
        let data = try Data(contentsOf: url)
        let messages = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String]
        return messages
    } catch {
        print("Error loading localized messages for locale \(locale): \(error)")
        return nil
    }
}

}`

func didReceive is where you modify the notification title and content base on the userInfo you include in the aps payload. This is pretty much all you need.