@@ -33,6 +33,8 @@ + (instancetype)sharedInstance {
33
33
__strong static RNFBMessagingAppDelegate *sharedInstance;
34
34
dispatch_once (&once, ^{
35
35
sharedInstance = [[RNFBMessagingAppDelegate alloc ] init ];
36
+ sharedInstance.conditionBackgroundMessageHandlerSet = [[NSCondition alloc ] init ];
37
+ sharedInstance.backgroundMessageHandlerSet = NO ;
36
38
});
37
39
return sharedInstance;
38
40
}
@@ -66,6 +68,16 @@ - (void)observe {
66
68
});
67
69
}
68
70
71
+ // used to signal that a javascript handler for background messages is set
72
+ - (void )signalBackgroundMessageHandlerSet {
73
+ RNFBMessagingAppDelegate *sharedInstance = [RNFBMessagingAppDelegate sharedInstance ];
74
+ [sharedInstance.conditionBackgroundMessageHandlerSet lock ];
75
+ DLog (@" signalBackgroundMessageHandlerSet sharedInstance.backgroundMessageHandlerSet was %@ " , sharedInstance.backgroundMessageHandlerSet ? @" YES" : @" NO" );
76
+ sharedInstance.backgroundMessageHandlerSet = YES ;
77
+ [sharedInstance.conditionBackgroundMessageHandlerSet broadcast ];
78
+ [sharedInstance.conditionBackgroundMessageHandlerSet unlock ];
79
+ }
80
+
69
81
// used to temporarily store a promise instance to resolve calls to `registerForRemoteNotifications`
70
82
- (void )setPromiseResolve : (RCTPromiseResolveBlock)resolve andPromiseReject : (RCTPromiseRejectBlock)reject {
71
83
_registerPromiseResolver = resolve;
@@ -102,6 +114,7 @@ - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotif
102
114
- (void )application : (UIApplication *)application didReceiveRemoteNotification : (NSDictionary *)userInfo fetchCompletionHandler : (void (^)(UIBackgroundFetchResult result))completionHandler {
103
115
#if __has_include(<FirebaseAuth/FirebaseAuth.h>)
104
116
if ([[FIRAuth auth ] canHandleNotification: userInfo]) {
117
+ DLog (@" didReceiveRemoteNotification Firebase Auth handeled the notification" );
105
118
completionHandler (UIBackgroundFetchResultNoData);
106
119
return ;
107
120
}
@@ -110,6 +123,8 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N
110
123
[[NSNotificationCenter defaultCenter ] postNotificationName: @" RNFBMessagingDidReceiveRemoteNotification" object: userInfo];
111
124
112
125
if (userInfo[@" gcm.message_id" ]) {
126
+ DLog (@" didReceiveRemoteNotification gcm.message_id was present %@ " , userInfo);
127
+
113
128
if ([UIApplication sharedApplication ].applicationState == UIApplicationStateBackground) {
114
129
// If app is in background state, register background task to guarantee async queues aren't frozen.
115
130
UIBackgroundTaskIdentifier __block backgroundTaskId = [application beginBackgroundTaskWithExpirationHandler: ^{
@@ -129,13 +144,46 @@ - (void)application:(UIApplication *)application didReceiveRemoteNotification:(N
129
144
}
130
145
});
131
146
132
- // TODO investigate later - RN bridge gets invalidated at start when in background and a new bridge created - losing all events
133
- // TODO so we just delay sending the event for a few seconds as a workaround
134
- // TODO most likely Remote Debugging causing bridge to be invalidated
135
- dispatch_after (dispatch_time (DISPATCH_TIME_NOW, (int64_t ) (8 * NSEC_PER_SEC)), dispatch_get_main_queue (), ^{
136
- [[RNFBRCTEventEmitter shared ] sendEventWithName: @" messaging_message_received_background" body: [RNFBMessagingSerializer remoteMessageUserInfoToDict: userInfo]];
137
- });
138
- } else {
147
+ RNFBMessagingAppDelegate *sharedInstance = [RNFBMessagingAppDelegate sharedInstance ];
148
+ [sharedInstance.conditionBackgroundMessageHandlerSet lock ];
149
+ @try {
150
+ DLog (@" didReceiveRemoteNotification sharedInstance.backgroundMessageHandlerSet = %@ " , sharedInstance.backgroundMessageHandlerSet ? @" YES" : @" NO" );
151
+ if (sharedInstance.backgroundMessageHandlerSet ) {
152
+ // Normal path, backgroundMessageHandlerSet has already been set, queue the notification for immediate delivery
153
+ dispatch_async (dispatch_get_main_queue (), ^{
154
+ [[RNFBRCTEventEmitter shared ] sendEventWithName: @" messaging_message_received_background" body: [RNFBMessagingSerializer remoteMessageUserInfoToDict: userInfo]];
155
+ });
156
+ DLog (@" didReceiveRemoteNotification without waiting for backgroundMessageHandlerSet to be set" );
157
+ } else {
158
+ // This spin needs to be on a background/concurrent queue to await the setup of backgroundMessageHandlerSet and not block the main thread
159
+ dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0 ), ^{
160
+ // Reaquire the lock in this new closure
161
+ [sharedInstance.conditionBackgroundMessageHandlerSet lock ];
162
+ @try {
163
+ // Spin/wait until backgroundMessageHandlerSet
164
+ // NB it is possible while this closure was being scheduled that backgroundMessageHandlerSet is already set and this loop is skipped
165
+ while (!sharedInstance.backgroundMessageHandlerSet ) {
166
+ DLog (@" didReceiveRemoteNotification waiting for sharedInstance.backgroundMessageHandlerSet %@ " , sharedInstance.backgroundMessageHandlerSet ? @" YES" : @" NO" );
167
+ if (![sharedInstance.conditionBackgroundMessageHandlerSet waitUntilDate: [NSDate dateWithTimeIntervalSinceNow: 25 ]]) {
168
+ // If after 25 seconds the client hasn't called backgroundMessageHandlerSet, give up on this notification
169
+ ELog (@" didReceiveRemoteNotification timed out waiting for sharedInstance.backgroundMessageHandlerSet" );
170
+ return ;
171
+ }
172
+ }
173
+ dispatch_async (dispatch_get_main_queue (), ^{
174
+ [[RNFBRCTEventEmitter shared ] sendEventWithName: @" messaging_message_received_background" body: [RNFBMessagingSerializer remoteMessageUserInfoToDict: userInfo]];
175
+ });
176
+ DLog (@" didReceiveRemoteNotification after waiting for backgroundMessageHandlerSet" );
177
+ } @finally {
178
+ [sharedInstance.conditionBackgroundMessageHandlerSet unlock ];
179
+ }
180
+ });
181
+ }
182
+ } @finally {
183
+ [sharedInstance.conditionBackgroundMessageHandlerSet unlock ];
184
+ }
185
+ } else {
186
+ DLog (@" didReceiveRemoteNotification while app was in foreground" );
139
187
[[RNFBRCTEventEmitter shared ] sendEventWithName: @" messaging_message_received" body: [RNFBMessagingSerializer remoteMessageUserInfoToDict: userInfo]];
140
188
completionHandler (UIBackgroundFetchResultNoData);
141
189
}
0 commit comments