From 53365c6315752b91d2f95f6c3cff60d1ea1218a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=A8=E3=83=AA=E3=82=B9?= Date: Tue, 4 Feb 2025 15:36:06 +0900 Subject: [PATCH] fix(ios): deliver payload to frontend handler when app in background --- docs/API.md | 1 + src/ios/PushPlugin.m | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/docs/API.md b/docs/API.md index 5d85be2fa..0cfbcdfe8 100644 --- a/docs/API.md +++ b/docs/API.md @@ -389,6 +389,7 @@ The event `notification` will be triggered each time a push notification is rece | `data.additionalData.foreground` | `boolean` | Whether the notification was received while the app was in the foreground | | `data.additionalData.coldstart` | `boolean` | Will be `true` if the application is started by clicking on the push notification, `false` if the app is already started. | | `data.additionalData.dismissed` | `boolean` | Is set to `true` if the notification was dismissed by the user | +| `data.additionalData.applicationState` | `number` | (iOS Only Flag) Contains the application state of the received notification. 0: `UIApplicationStateActive`, 1: `UIApplicationStateInactive`, 2: `UIApplicationStateBackground` | ### Example diff --git a/src/ios/PushPlugin.m b/src/ios/PushPlugin.m index 616e0205d..0e1aecff4 100644 --- a/src/ios/PushPlugin.m +++ b/src/ios/PushPlugin.m @@ -192,9 +192,9 @@ - (void)init:(CDVInvokedUrlCommand *)command { [center setNotificationCategories:[settings categories]]; // If there is a pending startup notification, we will delay to allow JS event handlers to setup - if (self.notificationMessage && !self.isInitialized) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self performSelector:@selector(notificationReceived) withObject:nil afterDelay: 0.5]; + if (self.notificationMessage) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self notificationReceived:YES]; }); } @@ -489,6 +489,10 @@ - (void)didReceiveNotificationResponse:(NSNotification *)notification { } - (void)notificationReceived { + [self notificationReceived:NO]; +} + +- (void)notificationReceived:(BOOL)shouldForceClear { NSLog(@"[PushPlugin] Notification received"); if (self.notificationMessage && self.callbackId != nil) @@ -502,9 +506,7 @@ - (void)notificationReceived { if ([[mutableNotificationMessage objectForKey:@"actionCallback"] isEqualToString:UNNotificationDefaultActionIdentifier]) { [mutableNotificationMessage removeObjectForKey:@"actionCallback"]; } - // @todo do not sent applicationState data to front for now. Figure out if we can add - // similar data to the other platforms. - [mutableNotificationMessage removeObjectForKey:@"applicationState"]; + self.notificationMessage = [mutableNotificationMessage copy]; for (id key in self.notificationMessage) { @@ -567,9 +569,25 @@ - (void)notificationReceived { [pluginResult setKeepCallbackAsBool:YES]; [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId]; + // When application state is inactive, do not clear notificationMessage. + // The init method will trigger when returning to foreground and trigger notification process. + NSNumber *applicationState = self.notificationMessage[@"applicationState"]; + if (applicationState && [applicationState isKindOfClass:[NSNumber class]]) { + if ([applicationState integerValue] != UIApplicationStateInactive) { + self.notificationMessage = nil; + } + } else { + // Handle unexpected cases where applicationState is missing or invalid + self.notificationMessage = nil; + } + + // Force clear comes from init. This ensure that it will be processed once. + if (shouldForceClear) { + self.notificationMessage = nil; + } + self.coldstart = NO; self.isForeground = NO; - self.notificationMessage = nil; } }