Skip to content

Commit c603816

Browse files
committed
feat(messaging, ios): Background Completion Handler from JS
1 parent 0103e12 commit c603816

File tree

4 files changed

+40
-15
lines changed

4 files changed

+40
-15
lines changed

packages/messaging/ios/RNFBMessaging/RNFBMessaging+AppDelegate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ NS_ASSUME_NONNULL_BEGIN
2727
@property _Nullable RCTPromiseResolveBlock registerPromiseResolver;
2828
@property(nonatomic, strong) NSCondition *conditionBackgroundMessageHandlerSet;
2929
@property(nonatomic) BOOL backgroundMessageHandlerSet;
30+
@property(nonatomic, copy) void (^completionHandler)(UIBackgroundFetchResult);
31+
@property(nonatomic, assign) UIBackgroundTaskIdentifier backgroundTaskId;
3032

3133
+ (_Nonnull instancetype)sharedInstance;
3234

packages/messaging/ios/RNFBMessaging/RNFBMessaging+AppDelegate.m

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -156,30 +156,34 @@ - (void)application:(UIApplication *)application
156156
DLog(@"didReceiveRemoteNotification gcm.message_id was present %@", userInfo);
157157

158158
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
159+
// Store the completion handler to call later when the JS code finishes
160+
RNFBMessagingAppDelegate *sharedInstance = [RNFBMessagingAppDelegate sharedInstance];
161+
sharedInstance.completionHandler = completionHandler;
162+
159163
// If app is in background state, register background task to guarantee async queues aren't
160164
// frozen.
161-
UIBackgroundTaskIdentifier __block backgroundTaskId =
162-
[application beginBackgroundTaskWithExpirationHandler:^{
163-
if (backgroundTaskId != UIBackgroundTaskInvalid) {
164-
[application endBackgroundTask:backgroundTaskId];
165-
backgroundTaskId = UIBackgroundTaskInvalid;
166-
}
167-
}];
168-
// TODO add support in a later version for calling completion handler directly from JS when
169-
// user JS code complete
165+
sharedInstance.backgroundTaskId = [application beginBackgroundTaskWithExpirationHandler:^{
166+
if (backgroundTaskId != UIBackgroundTaskInvalid) {
167+
[application endBackgroundTask:backgroundTaskId];
168+
backgroundTaskId = UIBackgroundTaskInvalid;
169+
}
170+
}];
171+
170172
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(25 * NSEC_PER_SEC)),
171173
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
172-
completionHandler(UIBackgroundFetchResultNewData);
174+
if (sharedInstance.completionHandler) {
175+
sharedInstance.completionHandler(UIBackgroundFetchResultNewData);
176+
sharedInstance.completionHandler = nil;
177+
}
173178

174179
// Stop background task after the longest timeout, async queue is okay to
175180
// freeze again after handling period
176-
if (backgroundTaskId != UIBackgroundTaskInvalid) {
177-
[application endBackgroundTask:backgroundTaskId];
178-
backgroundTaskId = UIBackgroundTaskInvalid;
181+
if (sharedInstance.backgroundTaskId != UIBackgroundTaskInvalid) {
182+
[application endBackgroundTask:sharedInstance.backgroundTaskId];
183+
sharedInstance.backgroundTaskId = UIBackgroundTaskInvalid;
179184
}
180185
});
181186

182-
RNFBMessagingAppDelegate *sharedInstance = [RNFBMessagingAppDelegate sharedInstance];
183187
[sharedInstance.conditionBackgroundMessageHandlerSet lock];
184188
@try {
185189
DLog(@"didReceiveRemoteNotification sharedInstance.backgroundMessageHandlerSet = %@",

packages/messaging/ios/RNFBMessaging/RNFBMessagingModule.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,19 @@ - (NSDictionary *)constantsToExport {
219219
return resolve(@([RCTConvert BOOL:@(notifCenter.isHeadless)]));
220220
}
221221

222+
RCT_EXPORT_METHOD(completeNotificationProcessing) {
223+
RNFBMessagingAppDelegate *appDelegate = [RNFBMessagingAppDelegate sharedInstance];
224+
if (appDelegate.completionHandler) {
225+
appDelegate.completionHandler(UIBackgroundFetchResultNewData);
226+
appDelegate.completionHandler = nil;
227+
}
228+
229+
if (appDelegate.backgroundTaskId != UIBackgroundTaskInvalid) {
230+
[[UIApplication sharedApplication] endBackgroundTask:appDelegate.backgroundTaskId];
231+
appDelegate.backgroundTaskId = UIBackgroundTaskInvalid;
232+
}
233+
}
234+
222235
RCT_EXPORT_METHOD(requestPermission
223236
: (NSDictionary *)permissions
224237
: (RCTPromiseResolveBlock)resolve

packages/messaging/lib/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,13 @@ class FirebaseMessagingModule extends FirebaseModule {
9898
return Promise.resolve();
9999
}
100100

101-
return backgroundMessageHandler(remoteMessage);
101+
// Ensure the handler is a promise
102+
const handlerPromise = Promise.resolve(backgroundMessageHandler(remoteMessage));
103+
handlerPromise.finally(() => {
104+
this.native.completeNotificationProcessing();
105+
});
106+
107+
return handlerPromise;
102108
});
103109

104110
this.emitter.addListener('messaging_settings_for_notification_opened', remoteMessage => {

0 commit comments

Comments
 (0)