Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions Libraries/PushNotificationIOS/PushNotificationIOS.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FetchResult type referenced from value position type FetchResult

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

property FetchResult Property not found in statics of PushNotificationIOS

* // 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
* {
Expand All @@ -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.
Expand Down Expand Up @@ -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:
Expand All @@ -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
*/
Expand Down
3 changes: 3 additions & 0 deletions Libraries/PushNotificationIOS/RCTPushNotificationManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 45 additions & 4 deletions Libraries/PushNotificationIOS/RCTPushNotificationManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ @implementation RCTConvert (NSCalendarUnit)

@end

@interface RCTPushNotificationManager ()
@property (nonatomic, strong) NSMutableDictionary *remoteNotificationCallbacks;
@end

@implementation RCTConvert (UILocalNotification)

+ (UILocalNotification *)UILocalNotification:(id)json
Expand All @@ -58,6 +62,12 @@ + (UILocalNotification *)UILocalNotification:(id)json
return notification;
}

RCT_ENUM_CONVERTER(UIBackgroundFetchResult, (@{
@"UIBackgroundFetchResultNewData": @(UIBackgroundFetchResultNewData),
@"UIBackgroundFetchResultNoData": @(UIBackgroundFetchResultNoData),
@"UIBackgroundFetchResultFailed": @(UIBackgroundFetchResultFailed),
}), UIBackgroundFetchResultNoData, integerValue)

@end
#endif //TARGET_OS_TV

Expand Down Expand Up @@ -167,9 +177,19 @@ + (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error

+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
{
NSDictionary *userInfo = @{@"notification": notification};
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
object:self
userInfo:userInfo];
}

+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
fetchCompletionHandler:(RCTRemoteNotificationCallback)completionHandler
{
NSDictionary *userInfo = @{@"notification": notification, @"completionHandler": completionHandler};
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
object:self
userInfo:notification];
userInfo:userInfo];
}

+ (void)didReceiveLocalNotification:(UILocalNotification *)notification
Expand All @@ -186,9 +206,20 @@ - (void)handleLocalNotificationReceived:(NSNotification *)notification

- (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];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you sending the event twice?

Copy link
Copy Markdown
Contributor Author

@JAStanton JAStanton Aug 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops! Bad merge

}

- (void)handleRemoteNotificationsRegistered:(NSNotification *)notification
Expand Down Expand Up @@ -224,6 +255,16 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
_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
*/
Expand Down