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.73k stars 3.98k forks source link

[firebase_messaging]: iOS onBackgroundMessage is not invoked in release mode #13643

Closed takatomatsumura closed 3 weeks ago

takatomatsumura commented 4 weeks ago

Is there an existing issue for this?

Are you aware of the differences between iOS and Android background message handling?

Do you have an active Apple Developer account?

Are you using a physical iOS device to test background messages?

Have you enabled "Remote Notifications" & "Background Mode" (Checking options for "Background Processing" & "Remote Notifications") in your app's Xcode project?

ใ‚นใ‚ฏใƒชใƒผใƒณใ‚ทใƒงใƒƒใƒˆ 2024-11-03 2 38 05

Have you created an APNs key in your Apple Developer account & uploaded this APNs key to your Firebase console?

console firebase google com_project_settings_cloudmessaging

Have you disabled method swizzling for Firebase in your app?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CADisableMinimumFrameDurationOnPhone</key>
    <true/>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleDisplayName</key>
    <string>$(PRODUCT_NAME)</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleLocalizations</key>
    <array>
        <string>ja</string>
    </array>
    <key>CFBundleName</key>
    <string>Example</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>$(FLUTTER_BUILD_NAME)</string>
    <key>CFBundleSignature</key>
    <string>com.example</string>
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>example</string>
            </array>
        </dict>
    </array>
    <key>CFBundleVersion</key>
    <string>$(FLUTTER_BUILD_NUMBER)</string>
    <key>FirebaseAppDelegateProxyEnabled</key>
    <string>YES</string>
    <key>LSApplicationQueriesSchemes</key>
    <array>
        <string>https</string>
        <string>http</string>
    </array>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>NSAppleMusicUsageDescription</key>
    <string>NSAppleMusicUsageDescription</string>
    <key>NSCameraUsageDescription</key>
    <string>NSCameraUsageDescription</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>NSPhotoLibraryUsageDescription</string>
    <key>NSUserNotificationsUsageDescription</key>
    <string>$(PRODUCT_NAME)ใ‹ใ‚‰ใฎ้€š็Ÿฅใ‚’ๅ—ใ‘ๅ–ใ‚‹ใซใฏ่จฑๅฏใŒๅฟ…่ฆใงใ™</string>
    <key>UIApplicationSupportsIndirectInputEvents</key>
    <true/>
    <key>UIBackgroundModes</key>
    <array>
        <string>fetch</string>
        <string>remote-notification</string>
        <string>processing</string>
    </array>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIMainStoryboardFile</key>
    <string>Main</string>
    <key>UIStatusBarHidden</key>
    <false/>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
</dict>
</plist>

Are you sending messages to your app from the Firebase Admin SDK?

I use firebase example for sending message. My snippet is below.

I add required headers, such as "priority" on Android and "content-available" on iOS.

from firebase_admin import credentials, initialize_app, messaging

# cred = credentials.RefreshToken("credentials.json")
default_app = initialize_app(credential=credentials.Certificate("credentials.json"))

# This registration token comes from the client FCM SDKs.
registration_token = "<device_token>"

# See documentation on defining a message payload.
message = messaging.Message(
    notification=messaging.Notification(title="TEST TITLE", body="TEST BODY"),
    data={
        "score": "850",
        "time": "2:45",
    },
    android=messaging.AndroidConfig(priority="high"),
    apns=messaging.APNSConfig(
        payload=messaging.APNSPayload(aps=messaging.Aps(content_available=True)),
        headers={"apns-priority": "5"},
    ),
    token=registration_token,
)

# Send a message to the device corresponding to the provided
# registration token.
response = messaging.send(message)
# Response is a message ID string.
print("Successfully sent message:", response)

Have you requested permission from the user to receive notifications?

Have you used the 'Console' application on your macOS device to check if the iOS device's system is throttling your background messages?

ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.662028+0900 SpringBoard Received incoming message on topic com.example at priority 10 ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.673029+0900 SpringBoard [com.example] Received remote notification request 7E65-E90C [ waking: 0, hasAlertContent: 1, hasSound: 0 hasBadge: 0 hasContentAvailable: 1 hasMutableContent: 0 pushType: Alert] ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.673408+0900 SpringBoard [com.example] Process delivery of push notification 7E65-E90C ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.673753+0900 SpringBoard [com.example] Request DUET delivers content-available push notification to application ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.674520+0900 SpringBoard SUBMITTING: com.apple.pushLaunch.com.example:39932D ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.675441+0900 SpringBoard [com.example] Badge can be set for notification 7E65-E90C: 0 [ canBadge: 1 badgeNumber: (null) ] ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.675678+0900 SpringBoard Getting effectiveSectionInfo for section identifier: com.example ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.675880+0900 SpringBoard [com.example] Getting effective section info ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.677206+0900 dasd Submitted Activity: com.apple.pushLaunch.com.example:39932D at priority 10 (Sun Nov 3 04:32:50 2024 - Mon Nov 4 04:32:50 2024) ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.677639+0900 SpringBoard [com.example] Got effective section info [ hasResult: 1 ] ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.677850+0900 SpringBoard Getting effectiveSectionInfo for section identifier: com.example ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.678046+0900 SpringBoard [com.example] Getting effective section info ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.679086+0900 SpringBoard [com.example] Got effective section info [ hasResult: 1 ] ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.679431+0900 SpringBoard [com.example] Saving notification 7E65-E90C: YES [ hasAlertContent: YES, shouldPresentAlert: YES settingsShouldSave: YES] ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.680068+0900 dasd Daemon Canceling Activities: {( com.apple.pushLaunch.com.example:731C6D )} ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.680233+0900 dasd CANCELED: com.apple.pushLaunch.com.example:731C6D at priority 10 ! ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.718648+0900 SpringBoard [com.example] Delivered user visible push notification 7E65-E90C ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.727308+0900 SpringBoard [com.example] Load 0 pending notification dictionaries ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.727812+0900 SpringBoard [com.example] Adding notification 7E65-E90C [ hasAlertContent: 1, shouldPresentAlert: 1 hasSound: 0 shouldPlaySound: 1 ]; interruption-level: 1; destinations 398: ( NotificationCenter, LockScreen, Alert, Spoken, Forwarding ) ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.728473+0900 SpringBoard BBDataProviderProxy com.example has enqueued a bulletin request ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.728648+0900 SpringBoard BBDataProviderProxy com.example is now sending enqueued bulletin request to BBServer ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.729482+0900 SpringBoard Publishing bulletin for section : subsectionIDs: (null), bulletinID = <64AD7851-AF33-4FE4-946C-B3E3ACACFAE3>, expiration date = <Sun Nov 10 04:32:50 2024>, expiration events <0> ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.734751+0900 SpringBoard NCBulletinNotificationSource adding bulletin 7E65-E90C for feed 3115 in section com.example ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.743469+0900 SpringBoard [com.apple.springboard.NCBulletinNotificationSource:0BB2CF28-AE1D-4DAE-8C8B-F6A5752A93DD] Resolving behavior for event, details=<DNDMutableClientEventDetails: 0x303cb9720; identifier: 'E0346579-3961-40F5-ADC6-B54BD8CA6576'; bundleIdentifier:: com.example; type: Default; urgency: Default; sender: (null); threadIdentifier: E3BBBB1022DC9959; filterCritera: (null); notifyAnyway: 0; behavior: Default> ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.744395+0900 donotdisturbd Event was resolved: resolution=<DNDSEventBehaviorResolution: 0x66492ce40; UUID: D9574973-7427-4816-95FD-7D2EA22124DA; date: 2024-11-02 19:32:50 +0000; eventBehavior: <DNDClientEventBehavior: 0x6642d7e70; eventDetails: <DNDClientEventDetails: 0x6648f4dc0; identifier: 'E0346579-3961-40F5-ADC6-B54BD8CA6576'; bundleIdentifier:: com.example; type: Default; urgency: Default; sender: (null); threadIdentifier: E3BBBB1022DC9959; filterCritera: (null); notifyAnyway: 0; behavior: Default>; interruptionSuppression: none; resolutionReason: disabled; activeModeUUID: (null)>; clientIdentifier: 'com.apple.springboard.NCBulletinNotificationSource'; outcome: allowed; reason: disabled> ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.745058+0900 SpringBoard [com.apple.springboard.NCBulletinNotificationSource:0BB2CF28-AE1D-4DAE-8C8B-F6A5752A93DD] Resolved event, details=<DNDMutableClientEventDetails: 0x303cb9720; identifier: 'E0346579-3961-40F5-ADC6-B54BD8CA6576'; bundleIdentifier:: com.example; type: Default; urgency: Default; sender: (null); threadIdentifier: E3BBBB1022DC9959; filterCritera: (null); notifyAnyway: 0; behavior: Default> behavior=<DNDClientEventBehavior: 0x30119b6c0; eventDetails: <DNDClientEventDetails: 0x303fffb60; identifier: 'E0346579-3961-40F5-ADC6-B54BD8CA6576'; bundleIdentifier:: com.example; type: Default; urgency: Default; sender: (null); threadIdentifier: E3BBBB1022DC9959; filterCritera: (null); notifyAnyway: 0; behavior: Default>; interruptionSuppression: none; resolutionReason: disabled; activeModeUUID: (null)> ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.745439+0900 SpringBoard Posting notification id: 7E65-E90C; section: com.example; thread: E2B6-531F; category: ; timestamp: 2024-11-02 19:32:50 +0000; interruption-level: active; relevance-score: 0.00; filter-criteria: (null); actions: [ minimal: 0 (0 text), default: 0 (0 text) ]; destinations: [ {( BulletinDestinationCoverSheet, BulletinDestinationBanner, BulletinDestinationNotificationCenter, BulletinDestinationLockScreen )} ] ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.747673+0900 SpringBoard Incoming Section [NCNotificationStructuredSectionList] inserting notification request 7E65-E90C in existing group Group List [com.example:E2B6-531F] at index 0 ใƒ‡ใƒ•ใ‚ฉใƒซใƒˆ 04:32:50.747879+0900 SpringBoard Group List [com.example:E2B6-531F] inserting notification request 7E65-E90C at index 0

Additional context and comments

I referenced the Issue 13525, and I specified pubspec.yaml below. I used the version in which the issue is reported to be resolved. The notifications themselves are being received in any state, so the settings for FCM should be correct.

  firebase_core: "^3.6.0"
  firebase_messaging:
    git:
      url: https://github.com/firebase/flutterfire
      path: packages/firebase_messaging/firebase_messaging
      ref: 8ff0f88c512a0dde16f5906c36259b911e0d5de7
firebase_messaging:
  dependency: "direct main"
  description:
    path: "packages/firebase_messaging/firebase_messaging"
    ref: "8ff0f88c512a0dde16f5906c36259b911e0d5de7"
    resolved-ref: "8ff0f88c512a0dde16f5906c36259b911e0d5de7"
    url: "https://github.com/firebase/flutterfire"
  source: git
  version: "15.1.3"

I checked some pattern, combination build-mode(debug or profile or release) and app-state(foreground, background with app-alive, background with app-killed). I found success message in 'Console' application on macOS 'COMPLETED com.example:5EBC1B at priority 5 !'.

In my case, under background with app-alive state and debug-mode, FirebaseMessaging.onBackgroundMessage was invoked correctly. However, under background with app-alive and release-mode or background with app-alive and release-mode was not invoked. As mentioned above, I found cancelled background task message 'CANCELED: com.apple.pushLaunch.com.example:731C6D at priority 5 !'; It occasionally works, but the conditions are unclear.

In background-mode and profile-build, FirebaseMessaging.onBackgroundMessage was invoked and worked correctly.

I would like to add that, all build-mode and foreground-state is work correctly.

I also tested the latest version 15.1.3 as of November 2024, as well as the currently used version 15.0.4, but they did not work properly. I tried on iOS 18 and 17, but did not observe any significant differences between the OS versions.

SelaseKay commented 3 weeks ago

Duplicate of: https://github.com/firebase/flutterfire/issues/13442

pvc97 commented 3 weeks ago

@takatomatsumura I have the same issue, onBackgroundMessage only works in debug mode on some devices. Did you find a solution?

I've tested a bunch of devices:

takatomatsumura commented 3 weeks ago

@pvc97 In my case, the cause of the issue has been identified, but the solution is unclear.

Title

I reviewed the source code of firebase_admin to understand it and investigate the cause.

Conclusion

FirebaseMessaging.onBackgroundMessage is worked correctly, but it is likely that throttling in release mode is the reason that FirebaseMessaging.onBackgroundMessage is not invoked.

Background notification throttling documentation

You can find more details about Apple notifications Apple Developer "The Push Notifications primer".

To summarize about background notifications, background notifications are largely similar to alert notifications, but there are some crucial differences. Specifically, background notifications are limited by daily send limits, and they may not function under certain conditions, such as when the device has low battery.

This is also mentioned in this documentation about Pushing background updates to your App, that documentation states that the limit is 2 or 3 background notifications per day.

Investigation contents

I couldn't understand the reason why FirebaseMessaging.onBackgroundMessage sometimes was being called and sometimes not, so I decided to investigate further.

Check app behavior

In iOS, we are able to listen to receive notification by didReceiveRemoteNotification. Below, this is iOS native source code of firebase_messaging for invoking flutter FirebaseMessaging.onBackgroundMessage.

#if !TARGET_OS_OSX
// Called for silent messages (i.e. data only) in the foreground & background
- (BOOL)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {

#if __has_include(<FirebaseAuth/FirebaseAuth.h>)
  if ([FIRApp defaultApp] != nil && [[FIRAuth auth] canHandleNotification:userInfo]) {
    completionHandler(UIBackgroundFetchResultNoData);
    return YES;
  }
#endif
  NSDictionary *notificationDict =
      [FLTFirebaseMessagingPlugin remoteMessageUserInfoToDict:userInfo];
  // Only handle notifications from FCM.
  if (userInfo[@"gcm.message_id"]) {
    if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
      __block BOOL completed = NO;

      // If app is in background state, register background task to guarantee async queues aren't
      // frozen.
      UIBackgroundTaskIdentifier __block backgroundTaskId =
          [application beginBackgroundTaskWithExpirationHandler:^{
            @synchronized(self) {
              if (completed == NO) {
                completed = YES;
                completionHandler(UIBackgroundFetchResultNewData);
                if (backgroundTaskId != UIBackgroundTaskInvalid) {
                  [application endBackgroundTask:backgroundTaskId];
                  backgroundTaskId = UIBackgroundTaskInvalid;
                }
              }
            }
          }];

      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(25 * NSEC_PER_SEC)),
                     dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
                       @synchronized(self) {
                         if (completed == NO) {
                           completed = YES;
                           completionHandler(UIBackgroundFetchResultNewData);
                           if (backgroundTaskId != UIBackgroundTaskInvalid) {
                             [application endBackgroundTask:backgroundTaskId];
                             backgroundTaskId = UIBackgroundTaskInvalid;
                           }
                         }
                       }
                     });

      // This is my comment
      // invoke flutter backgroundHandler here
      [_channel invokeMethod:@"Messaging#onBackgroundMessage"
                   arguments:notificationDict
                      result:^(id _Nullable result) {
                        @synchronized(self) {
                          if (completed == NO) {
                            completed = YES;
                            completionHandler(UIBackgroundFetchResultNewData);
                            if (backgroundTaskId != UIBackgroundTaskInvalid) {
                              [application endBackgroundTask:backgroundTaskId];
                              backgroundTaskId = UIBackgroundTaskInvalid;
                            }
                          }
                        }
                      }];
    } else {
      // 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) {
        // This is my comment
        // invoke flutter onMessageHandler here
        [_channel invokeMethod:@"Messaging#onMessage" arguments:notificationDict];
      }
      completionHandler(UIBackgroundFetchResultNoData);
    }

    return YES;
  }  // if (userInfo[@"gcm.message_id"])
  return NO;
}  // didReceiveRemoteNotification
#endif

Then, I debugged to figure out whether the cause is in the iOS native code or the Flutter code by XCode and console-app of mac.

The firebase_messaging 15.1.4 was released, so I used firebase_messaging 15.1.4 of latest version.

My pubspec.lock ```text:pubspec.lock ... firebase_core: dependency: "direct main" description: name: firebase_core sha256: e59141ff83e70a9ba571a1f8733c5598cf57e6e68037ab185581d7fc0a436738 url: "https://pub.dev" source: hosted version: "3.7.0" ... firebase_messaging: dependency: "direct main" description: name: firebase_messaging sha256: a988c6ab37fa5a6abf2f8087a44b765e058848ace6f3253fb1602d1d44a63747 url: "https://pub.dev" source: hosted version: "15.1.4" ... ```

I used firebase-admin for sending fcm message.

Below, this is python-code for sending fcm message in background. ```python from firebase_admin import messaging registration_token = "token" message = messaging.Message( notification=messaging.Notification( title="TEST TITLE", body="This is test notification for iOS background throttling", ), data={"hello": "This is a Firebase Cloud Messaging device group message!"}, android=messaging.AndroidConfig(priority="high"), apns=messaging.APNSConfig( payload=messaging.APNSPayload( aps=messaging.Aps( content_available=True, sound="default", ), ), headers={"apns-priority": "5"}, ), token=registration_token, ) response = messaging.send(message) ```

The cause of not invoking FirebaseMessaging.onBackgroundMessage is that didReceiveRemoteNotification handler is not invoked. So, FirebaseMessaging.onBackgroundMessage is not called.

Debug result is also same as my report in the above, it seems that there is no throttling in debug-mode. I send message more than 20 message in a hour, all message was received.

However, as mentioned in the documentation, it seems that there is throttling in release-mode. I was throttled after sending it twice.

Detail of debug result | index | build mode | sent_at | receive app state | able to receive | invoke iOS native listener | mac console message | | ----: | ---------- | ------- | ----------------- | --------------- | -------------------------- | ------------------- | | 1 | debug | 2024-11-09 01:24:00 | Foreground app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 2 | debug | 2024-11-09 01:26:03 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 3 | debug | 2024-11-09 01:27:46 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 4 | debug | 2024-11-09 01:29:48 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 5 | debug | 2024-11-09 01:30:40 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 6 | debug | 2024-11-09 01:31:36 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 7 | debug | 2024-11-09 01:32:38 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 8 | debug | 2024-11-09 01:35:19 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 9 | debug | 2024-11-09 01:36:26 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 10 | debug | 2024-11-09 01:37:41 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 11 | debug | 2024-11-09 01:39:04 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 12 | debug | 2024-11-09T01:41:45 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 13 | debug | 2024-11-09T01:42:49 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 14 | debug | 2024-11-09T01:44:27 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 15 | debug | 2024-11-09T01:44:27 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 16 | debug | 2024-11-09T01:46:36 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 17 | debug | 2024-11-09T01:47:13 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 18 | debug | 2024-11-09T01:47:16 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 19 | debug | 2024-11-09T01:47:19 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 20 | debug | 2024-11-09T01:47:21 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 21 | debug | 2024-11-09T01:48:08 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 22 | release | 2024-11-09T01:52:14 | Background app and background notification | True | True | | | 23 | release | 2024-11-09T01:53:17 | Background app and background notification | True | True | | | 24 | release | 2024-11-09T01:53:45 | Background app and background notification | False | False | Daemon Canceling Activities: {( com.apple.pushLaunch.com.example.app:9206BE )} CANCELED: com.apple.pushLaunch.com.example.app at priority 5 ! | | 25 | release | 2024-11-09T01:54:39 | Background app and background notification | False | False | Daemon Canceling Activities: {( com.apple.pushLaunch.com.example.app:9206BE )} CANCELED: com.apple.pushLaunch.com.example.app at priority 5 ! | | 26 | release | 2024-11-09T01:55:54 | Background app and background notification | False | False | Daemon Canceling Activities: {( com.apple.pushLaunch.com.example.app:9206BE )} CANCELED: com.apple.pushLaunch.com.example.app at priority 5 ! | | 27 | debug | 2024-11-09T01:58:56 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 28 | debug | 2024-11-09T01:59:01 | Background app and background notification | True | True | COMPLETED com.apple.pushLaunch.com.example.app at priority 5 ! | | 29 | release | 2024-11-09T02:02:26 | Background app and background notification | False | False | Daemon Canceling Activities: {( com.apple.pushLaunch.com.example.app:9206BE )} CANCELED: com.apple.pushLaunch.com.example.app at priority 5 ! | | 30 | release | 2024-11-09T02:03:22 | Background app and background notification | False | False | Daemon Canceling Activities: {( com.apple.pushLaunch.com.example.app:9206BE )} CANCELED: com.apple.pushLaunch.com.example.app at priority 5 ! |
pvc97 commented 2 weeks ago

@takatomatsumura

This is also mentioned in this documentation about Pushing background updates to your App

This doc is about "Background notification":

A background notification is a remote notification that doesnโ€™t display an alert, play a sound, or badge your appโ€™s icon. It wakes your app in the background and gives it time to initiate downloads from your server and update its content.

However, you are sending messages that include both a notification title and content, and iOS can display them. I believe that a background notification refers to a message without notification content (only data). Therefore, throttling should not occur in this case.

takatomatsumura commented 2 weeks ago

@pvc97 As you mentioned, I sent the push notification as an alert notification.

According to the FCM documentation, there are the following types of notifications:

Also in the Apple documentation for Sending notification requests to APNs, the following types are mentioned:

I think, one notification could have the nature of multiple types such as alert notification & background notification, like Notification & Data.

In the Apple documentation for Generating a remote notification, alert and content-available are defined as follows:

alert
The information for displaying an alert. A dictionary is recommended. If you specify a string, the alert displays your string as the body text. For a list of dictionary keys, see Table 2.
content-available
The background notification flag. To perform a silent background update, specify the value 1 and donโ€™t include the alert, badge, or sound keys in your payload. See Pushing background updates to your App.

I believe that if both alert and content-available are specified, it is likely that the alert notification will be shown to the user, and the background processing will run as a background notification.

In my code, as defined above, since the content to be displayed to the user is specified in alert, it is an alert notification. And since content-type is also specified, it is probably considered a background notification as well.

message = messaging.Message(
    notification=messaging.Notification(
        title="TEST TITLE",
        body="This is test notification for iOS background throttling",
    ),
    data={"hello": "This is a Firebase Cloud Messaging device group message!"},
    ...
    apns=messaging.APNSConfig(
        payload=messaging.APNSPayload(
            aps=messaging.Aps(
                content_available=True,
                sound="default",
            ),
        ),
        headers={"apns-priority": "5"},
    ),
    ...
)

If it is processed as a background notification, throttling may occur on the device.