React-native-firebase: iOS remote notification handler and background data support

Created on 12 Apr 2018  路  11Comments  路  Source: invertase/react-native-firebase

Issue

In the 3.x versions of react-native-firebase, a finish method was available in the messaging module that allowed the developer to invoke the fetchCompletionHandler provided in the iOS app delegate method - (void)didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler. This mirrored the implementation provided in react native's own PushNotificationIOS implementation. According to the Apple documentation, that fetchCompletionHandler must be called, and should be called "as soon as possible".

This capability was removed in the 4.x overhaul, and the app-delegate-provided fetchCompletionHandler is now ignored.

Without a way to call that callback, iOS will consider background fetches executed through react-native-firebase as having the worst possible performance. In short order, silent pushes will be throttled or disabled for the app (this article has some good information on how the OS "punishes" apps with seemingly long running background tasks).

Environment

  1. Application Target Platform: iOS

  2. Development Operating System: N/A

  3. Build Tools: N/A

  4. React Native version: N/A

  5. RNFirebase Version: 4.0.1

  6. Firebase Module: notifications, messaging

Notifications General Needs Triage iOS

Most helpful comment

Support has been added in https://github.com/invertase/react-native-firebase/pull/1393, thanks to @ryanggrey :tada:

Will land in v5.0.0.

(this is background only support, foreground is to be discussed in https://github.com/invertase/react-native-firebase/issues/1408)


Loving react-native-firebase and the support we provide? Please consider supporting us with any of the below:

All 11 comments

We call the fetchCompletionHandler automatically when the notification has been sent over the bridge:

Here: https://github.com/invertase/react-native-firebase/blob/master/ios/RNFirebase/notifications/RNFirebaseNotifications.m#L105 and here: https://github.com/invertase/react-native-firebase/blob/master/ios/RNFirebase/notifications/RNFirebaseNotifications.m#L136

This is something that we could theoretically add back in, but I purposefully tried to keep things as simple as possible.

It turns out that there were a couple of places where completionHandler should have been being called, but wasn't. This has been updated pending release in v4.0.3.

I'd be interested in hearing your views on whether we should be giving more control over how this method should be called?

Thanks for the clarification. Things aren't quite as dire as I thought on first glance :)

I still think there's a need to give the developer control over when that callback is invoked. If my understanding is correct, the javascript that's executed in response to the event that's sent over the bridge happens asynchronously with respect to the native handler. That could be problematic if you want to do some work in the onMessage handler.

As an example, let's say we want to download some data from the server, do some data transformation, then store the result somewhere when we receive a silent push. Assuming the onMessage handler is executed asynchronously with respect to the native handler, consider this situation:

Native thread                 JS thread
--------------------------    ---------------------
+ Receive remote message 
+ Send event over bridge      + onMessage called
+ Call completionHandler      + perform http fetches
                              + wait for responses
                              + transform response data
                              + persist result

After completionHandler is called, iOS considers the background task done and may move the app back into a suspended state _at any time_. This means the event handling on the javascript side could be interrupted at any time during its execution, making it unlikely that you'll be able to perform the background work you want done before the OS suspends your app.

If you give callback capability to the javascript side, the above scenario becomes:

Native thread                 JS thread
--------------------------    ---------------------
+ Receive remote message 
+ Send event over bridge      + onMessage called
                              + perform http fetches
                              + wait for responses
                              + transform response data
                              + persist result
                              + call finish(UIBackgroundFetchResultNewData)
+ Call completionHandler

I'm also not thrilled with always calling the completion handler with UIBackgroundFetchResultNoData. It's unclear to me how those result values influence the DASD "scoring" of the app's performance, but I'd be much more comfortable following the Apple recommendations than sending the incorrect value when data _is_ retrieved or when we hit an error during background processing.

@chrisbianca any updates on the issue?

Still looking at the best way to implement this functionality.

Conceptually it鈥檚 quite simple, however as it鈥檚 possible for both FCM data-only messages and FCM notifications to need this added, but only in certain scenarios, we just need to work out where best to add it and make it easy for developers to use it.

any updates on this?
Thanks!

Is there a recommended workaround for those of us with deadlines?
;-)

Depends how comfortable you are with native code? ;)

The methods of interest are these:

1) https://github.com/invertase/react-native-firebase/blob/master/ios/RNFirebase/notifications/RNFirebaseNotifications.m#L100
2) https://github.com/invertase/react-native-firebase/blob/master/ios/RNFirebase/notifications/RNFirebaseNotifications.m#L189

The challenge is identifying how the handler is responded to and providing this flexibility to the developer without voiding some of the simplification that has been added along the way.

Depends how comfortable you are with native code? ;)

In order to make my deadlines, I am willing to make sacrifices, like learning new and exciting things.

Support has been added in https://github.com/invertase/react-native-firebase/pull/1393, thanks to @ryanggrey :tada:

Will land in v5.0.0.

(this is background only support, foreground is to be discussed in https://github.com/invertase/react-native-firebase/issues/1408)


Loving react-native-firebase and the support we provide? Please consider supporting us with any of the below:

Great works guys, really looking forward to it :clap:

Was this page helpful?
0 / 5 - 0 ratings