Remote notification completion handler
Summary: **Motivation** To allow handling of remote notifications using the preferred delegate [application:didReceiveRemoteNotification:fetchCompletionHandler](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:fetchCompletionHandler:). React native right now is setup to use [application:didReceiveRemoteNotification](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:) which doesn't give the engineer the option to call back to the app via a completion handler and inform the app that it is done with handling the push notification. The primary reason to use the `fetchCompletionHandler` would be to wake up the app to fetch updates so the next time the user opens the app it will be up to date. A new method will be exposed: `PushNotificationIOS# Closes https://github.com/facebook/react-native/pull/8040 Differential Revision: D4081766 Pulled By: bestander fbshipit-source-id: 2819061bd3a926cb1c9c743af5aabab8c0faec3d
This commit is contained in:
parent
a16d72842d
commit
e000b71845
|
@ -24,6 +24,12 @@ const NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered';
|
|||
const NOTIF_REGISTRATION_ERROR_EVENT = 'remoteNotificationRegistrationError';
|
||||
const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived';
|
||||
|
||||
export type FetchResult = {
|
||||
NewData: string,
|
||||
NoData: string,
|
||||
ResultFailed: string,
|
||||
};
|
||||
|
||||
/**
|
||||
* An event emitted by PushNotificationIOS.
|
||||
*/
|
||||
|
@ -84,6 +90,17 @@ export type PushNotificationEventName = $Enum<{
|
|||
* {
|
||||
* [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
|
||||
* }
|
||||
* // Required for the notification event. You must call the completion handler after handling the remote notification.
|
||||
* - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
|
||||
* fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
|
||||
* {
|
||||
* [RCTPushNotificationManager didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
|
||||
* }
|
||||
* // Optionally implement this method over the previous to receive remote notifications. However
|
||||
* // implement the application:didReceiveRemoteNotification:fetchCompletionHandler: method instead of this one whenever possible.
|
||||
* // If your delegate implements both methods, the app object calls the `application:didReceiveRemoteNotification:fetchCompletionHandler:` method
|
||||
* // Either this method or `application:didReceiveRemoteNotification:fetchCompletionHandler:` is required in order to receive remote notifications.
|
||||
* //
|
||||
* // Required for the registrationError event.
|
||||
* - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
|
||||
* {
|
||||
|
@ -106,6 +123,15 @@ class PushNotificationIOS {
|
|||
_alert: string | Object;
|
||||
_sound: string;
|
||||
_badgeCount: number;
|
||||
_notificationId: string;
|
||||
_isRemote: boolean;
|
||||
_remoteNotificationCompleteCalllbackCalled: boolean;
|
||||
|
||||
static FetchResult: FetchResult = {
|
||||
NewData: 'UIBackgroundFetchResultNewData',
|
||||
NoData: 'UIBackgroundFetchResultNoData',
|
||||
ResultFailed: 'UIBackgroundFetchResultFailed',
|
||||
};
|
||||
|
||||
/**
|
||||
* Schedules the localNotification for immediate presentation.
|
||||
|
@ -341,6 +367,11 @@ class PushNotificationIOS {
|
|||
*/
|
||||
constructor(nativeNotif: Object) {
|
||||
this._data = {};
|
||||
this._remoteNotificationCompleteCalllbackCalled = false;
|
||||
this._isRemote = nativeNotif.remote;
|
||||
if (this._isRemote) {
|
||||
this._notificationId = nativeNotif.notificationId;
|
||||
}
|
||||
|
||||
if (nativeNotif.remote) {
|
||||
// Extract data from Apple's `aps` dict as defined:
|
||||
|
@ -364,6 +395,28 @@ class PushNotificationIOS {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is available for remote notifications that have been received via:
|
||||
* `application:didReceiveRemoteNotification:fetchCompletionHandler:`
|
||||
* https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveRemoteNotification:fetchCompletionHandler:
|
||||
*
|
||||
* Call this to execute when the remote notification handling is complete. When
|
||||
* calling this block, pass in the fetch result value that best describes
|
||||
* the results of your operation. You *must* call this handler and should do so
|
||||
* as soon as possible. For a list of possible values, see `PushNotificationIOS.FetchResult`.
|
||||
*
|
||||
* If you do not call this method your background remote notifications could
|
||||
* be throttled, to read more about it see the above documentation link.
|
||||
*/
|
||||
finish(fetchResult: FetchResult) {
|
||||
if (!this._isRemote || !this._notificationId || this._remoteNotificationCompleteCalllbackCalled) {
|
||||
return;
|
||||
}
|
||||
this._remoteNotificationCompleteCalllbackCalled = true;
|
||||
|
||||
RCTPushNotificationManager.onFinishRemoteNotification(this._notificationId, fetchResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* An alias for `getAlert` to get the notification's main message string
|
||||
*/
|
||||
|
|
|
@ -11,10 +11,13 @@
|
|||
|
||||
@interface RCTPushNotificationManager : RCTEventEmitter
|
||||
|
||||
typedef void (^RCTRemoteNotificationCallback)(UIBackgroundFetchResult result);
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
+ (void)didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings;
|
||||
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
|
||||
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification;
|
||||
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification fetchCompletionHandler:(RCTRemoteNotificationCallback)completionHandler;
|
||||
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification;
|
||||
+ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,10 @@ RCT_ENUM_CONVERTER(NSCalendarUnit,
|
|||
|
||||
@end
|
||||
|
||||
@interface RCTPushNotificationManager ()
|
||||
@property (nonatomic, strong) NSMutableDictionary *remoteNotificationCallbacks;
|
||||
@end
|
||||
|
||||
@implementation RCTConvert (UILocalNotification)
|
||||
|
||||
+ (UILocalNotification *)UILocalNotification:(id)json
|
||||
|
@ -58,6 +62,12 @@ RCT_ENUM_CONVERTER(NSCalendarUnit,
|
|||
return notification;
|
||||
}
|
||||
|
||||
RCT_ENUM_CONVERTER(UIBackgroundFetchResult, (@{
|
||||
@"UIBackgroundFetchResultNewData": @(UIBackgroundFetchResultNewData),
|
||||
@"UIBackgroundFetchResultNoData": @(UIBackgroundFetchResultNoData),
|
||||
@"UIBackgroundFetchResultFailed": @(UIBackgroundFetchResultFailed),
|
||||
}), UIBackgroundFetchResultNoData, integerValue)
|
||||
|
||||
@end
|
||||
#endif //TARGET_OS_TV
|
||||
|
||||
|
@ -167,9 +177,19 @@ RCT_EXPORT_MODULE()
|
|||
|
||||
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
|
||||
{
|
||||
NSDictionary *userInfo = @{@"notification": notification};
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
|
||||
object:self
|
||||
userInfo:notification];
|
||||
userInfo:userInfo];
|
||||
}
|
||||
|
||||
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
|
||||
fetchCompletionHandler:(RCTRemoteNotificationCallback)completionHandler
|
||||
{
|
||||
NSDictionary *userInfo = @{@"notification": notification, @"completionHandler": completionHandler};
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
|
||||
object:self
|
||||
userInfo:userInfo];
|
||||
}
|
||||
|
||||
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification
|
||||
|
@ -186,9 +206,20 @@ RCT_EXPORT_MODULE()
|
|||
|
||||
- (void)handleRemoteNotificationReceived:(NSNotification *)notification
|
||||
{
|
||||
NSMutableDictionary *userInfo = [notification.userInfo mutableCopy];
|
||||
userInfo[@"remote"] = @YES;
|
||||
[self sendEventWithName:@"remoteNotificationReceived" body:userInfo];
|
||||
NSMutableDictionary *remoteNotification = [NSMutableDictionary dictionaryWithDictionary:notification.userInfo[@"notification"]];
|
||||
RCTRemoteNotificationCallback completionHandler = notification.userInfo[@"completionHandler"];
|
||||
NSString* notificationId = [[NSUUID UUID] UUIDString];
|
||||
remoteNotification[@"notificationId"] = notificationId;
|
||||
remoteNotification[@"remote"] = @YES;
|
||||
if (completionHandler) {
|
||||
if (!self.remoteNotificationCallbacks) {
|
||||
// Lazy initialization
|
||||
self.remoteNotificationCallbacks = [NSMutableDictionary dictionary];
|
||||
}
|
||||
self.remoteNotificationCallbacks[notificationId] = completionHandler;
|
||||
}
|
||||
|
||||
[self sendEventWithName:@"remoteNotificationReceived" body:notification.userInfo];
|
||||
}
|
||||
|
||||
- (void)handleRemoteNotificationsRegistered:(NSNotification *)notification
|
||||
|
@ -224,6 +255,16 @@ RCT_EXPORT_MODULE()
|
|||
_requestPermissionsResolveBlock = nil;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(onFinishRemoteNotification:(NSString*)notificationId fetchResult:(UIBackgroundFetchResult)result) {
|
||||
RCTRemoteNotificationCallback completionHandler = self.remoteNotificationCallbacks[notificationId];
|
||||
if (!completionHandler) {
|
||||
RCTLogError(@"There is no completion handler with notification id: %@", notificationId)
|
||||
return;
|
||||
}
|
||||
completionHandler(result);
|
||||
[self.remoteNotificationCallbacks removeObjectForKey:notificationId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the application icon badge number on the home screen
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue