From abe172aa213f119bd7bc73d6d47a83c0ba327058 Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Mon, 29 Aug 2016 14:17:46 -0700 Subject: [PATCH 1/3] Emit a registrationError event when failing to register for remote notifications (iOS) --- .../PushNotificationIOS.js | 25 ++++++++++++------ .../RCTPushNotificationManager.h | 1 + .../RCTPushNotificationManager.m | 26 ++++++++++++++++++- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/Libraries/PushNotificationIOS/PushNotificationIOS.js b/Libraries/PushNotificationIOS/PushNotificationIOS.js index 50f3269064126c..b981f926554686 100644 --- a/Libraries/PushNotificationIOS/PushNotificationIOS.js +++ b/Libraries/PushNotificationIOS/PushNotificationIOS.js @@ -21,6 +21,7 @@ const _notifHandlers = new Map(); const DEVICE_NOTIF_EVENT = 'remoteNotificationReceived'; const NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered'; +const NOTIF_REGISTRATION_ERROR_EVENT = 'remoteNotificationRegistrationError'; const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived'; /** @@ -56,6 +57,11 @@ const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived'; * { * [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; * } + * // Required for the registrationError event. + * - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error + * { + * [RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error]; + * } * // Required for the notification event. * - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification * { @@ -66,10 +72,6 @@ const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived'; * { * [RCTPushNotificationManager didReceiveLocalNotification:notification]; * } - * - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error - * { - * NSLog(@"%@", error); - * } * ``` */ class PushNotificationIOS { @@ -165,8 +167,8 @@ class PushNotificationIOS { */ static addEventListener(type: string, handler: Function) { invariant( - type === 'notification' || type === 'register' || type === 'localNotification', - 'PushNotificationIOS only supports `notification`, `register` and `localNotification` events' + type === 'notification' || type === 'register' || type === 'registrationError' || type === 'localNotification', + 'PushNotificationIOS only supports `notification`, `register`, `registrationError`, and `localNotification` events' ); var listener; if (type === 'notification') { @@ -190,6 +192,13 @@ class PushNotificationIOS { handler(registrationInfo.deviceToken); } ); + } else if (type === 'registrationError') { + listener = PushNotificationEmitter.addListener( + NOTIF_REGISTRATION_ERROR_EVENT, + (errorInfo) => { + handler(errorInfo); + } + ); } _notifHandlers.set(handler, listener); } @@ -200,8 +209,8 @@ class PushNotificationIOS { */ static removeEventListener(type: string, handler: Function) { invariant( - type === 'notification' || type === 'register' || type === 'localNotification', - 'PushNotificationIOS only supports `notification`, `register` and `localNotification` events' + type === 'notification' || type === 'register' || type === 'registrationError' || type === 'localNotification', + 'PushNotificationIOS only supports `notification`, `register`, `registrationError`, and `localNotification` events' ); var listener = _notifHandlers.get(handler); if (!listener) { diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.h b/Libraries/PushNotificationIOS/RCTPushNotificationManager.h index fe8158ce9a3c3a..99207dd601ed7e 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.h +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.h @@ -15,5 +15,6 @@ + (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; + (void)didReceiveRemoteNotification:(NSDictionary *)notification; + (void)didReceiveLocalNotification:(UILocalNotification *)notification; ++ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error; @end diff --git a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m index 89d5138d8f6659..e4ad7d864da71d 100644 --- a/Libraries/PushNotificationIOS/RCTPushNotificationManager.m +++ b/Libraries/PushNotificationIOS/RCTPushNotificationManager.m @@ -20,6 +20,7 @@ NSString *const RCTRegisterUserNotificationSettings = @"RegisterUserNotificationSettings"; NSString *const RCTErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS"; +NSString *const RCTErrorRemoteNotificationRegistrationFailed = @"E_FAILED_TO_REGISTER_FOR_REMOTE_NOTIFICATIONS"; @implementation RCTConvert (UILocalNotification) @@ -86,6 +87,10 @@ - (void)startObserving selector:@selector(handleRemoteNotificationsRegistered:) name:RCTRemoteNotificationsRegistered object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleRemoteNotificationRegistrationError:) + name:RCTErrorRemoteNotificationRegistrationFailed + object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleRegisterUserNotificationSettings:) name:RCTRegisterUserNotificationSettings @@ -101,7 +106,8 @@ - (void)stopObserving { return @[@"localNotificationReceived", @"remoteNotificationReceived", - @"remoteNotificationsRegistered"]; + @"remoteNotificationsRegistered", + @"remoteNotificationRegistrationError"]; } + (void)didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings *)notificationSettings @@ -127,6 +133,13 @@ + (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken userInfo:@{@"deviceToken" : [hexString copy]}]; } ++ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +{ + [[NSNotificationCenter defaultCenter] postNotificationName:RCTErrorRemoteNotificationRegistrationFailed + object:self + userInfo:@{@"error": error}]; +} + + (void)didReceiveRemoteNotification:(NSDictionary *)notification { [[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived @@ -158,6 +171,17 @@ - (void)handleRemoteNotificationsRegistered:(NSNotification *)notification [self sendEventWithName:@"remoteNotificationsRegistered" body:notification.userInfo]; } +- (void)handleRemoteNotificationRegistrationError:(NSNotification *)notification +{ + NSError *error = notification.userInfo[@"error"]; + NSDictionary *errorDetails = @{ + @"message": error.localizedDescription, + @"code": @(error.code), + @"details": error.userInfo, + }; + [self sendEventWithName:@"remoteNotificationRegistrationError" body:errorDetails]; +} + - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification { if (_requestPermissionsResolveBlock == nil) { From 722e6ffd951ce4de8d9801ba0c58efc09821d7c0 Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Mon, 29 Aug 2016 14:19:43 -0700 Subject: [PATCH 2/3] UIExplorer updates to better handle push notifications --- Examples/UIExplorer/UIExplorer/AppDelegate.m | 33 +++++++++++++++ .../js/PushNotificationIOSExample.js | 40 ++++++++++++++----- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/Examples/UIExplorer/UIExplorer/AppDelegate.m b/Examples/UIExplorer/UIExplorer/AppDelegate.m index 822ea8aef3217f..033def392a8a88 100644 --- a/Examples/UIExplorer/UIExplorer/AppDelegate.m +++ b/Examples/UIExplorer/UIExplorer/AppDelegate.m @@ -19,6 +19,7 @@ #import "RCTJavaScriptLoader.h" #import "RCTLinkingManager.h" #import "RCTRootView.h" +#import "RCTPushNotificationManager.h" @interface AppDelegate() @@ -76,4 +77,36 @@ - (void)loadSourceForBridge:(RCTBridge *)bridge onComplete:loadCallback]; } +# pragma mark - Push Notifications + +// Required to register for notifications +- (void)application:(UIApplication *)__unused application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings +{ + [RCTPushNotificationManager didRegisterUserNotificationSettings:notificationSettings]; +} + +// Required for the remoteNotificationsRegistered event. +- (void)application:(UIApplication *)__unused application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken +{ + [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; +} + +// Required for the remoteNotificationRegistrationError event. +- (void)application:(UIApplication *)__unused application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error +{ + [RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error]; +} + +// Required for the remoteNotificationReceived event. +- (void)application:(UIApplication *)__unused application didReceiveRemoteNotification:(NSDictionary *)notification +{ + [RCTPushNotificationManager didReceiveRemoteNotification:notification]; +} + +// Required for the localNotificationReceived event. +- (void)application:(UIApplication *)__unused application didReceiveLocalNotification:(UILocalNotification *)notification +{ + [RCTPushNotificationManager didReceiveLocalNotification:notification]; +} + @end diff --git a/Examples/UIExplorer/js/PushNotificationIOSExample.js b/Examples/UIExplorer/js/PushNotificationIOSExample.js index e0c961b49f4dc7..4be80a6c7702a9 100644 --- a/Examples/UIExplorer/js/PushNotificationIOSExample.js +++ b/Examples/UIExplorer/js/PushNotificationIOSExample.js @@ -50,16 +50,18 @@ class Button extends React.Component { class NotificationExample extends React.Component { componentWillMount() { - // Add listener for push notifications - PushNotificationIOS.addEventListener('notification', this._onNotification); - // Add listener for local notifications + PushNotificationIOS.requestPermissions(); + + PushNotificationIOS.addEventListener('register', this._onRegistered); + PushNotificationIOS.addEventListener('registrationError', this._onRegistrationError); + PushNotificationIOS.addEventListener('notification', this._onRemoteNotification); PushNotificationIOS.addEventListener('localNotification', this._onLocalNotification); } componentWillUnmount() { - // Remove listener for push notifications - PushNotificationIOS.removeEventListener('notification', this._onNotification); - // Remove listener for local notifications + PushNotificationIOS.removeEventListener('register', this._onRegistered); + PushNotificationIOS.removeEventListener('registrationError', this._onRegistrationError); + PushNotificationIOS.removeEventListener('notification', this._onRemoteNotification); PushNotificationIOS.removeEventListener('localNotification', this._onLocalNotification); } @@ -101,7 +103,29 @@ class NotificationExample extends React.Component { }); } - _onNotification(notification) { + _onRegistered(deviceToken) { + AlertIOS.alert( + 'Registered For Remote Push', + `Device Token: ${deviceToken}`, + [{ + text: 'Dismiss', + onPress: null, + }] + ); + } + + _onRegistrationError(error) { + AlertIOS.alert( + 'Failed To Register For Remote Push', + `Error (${error.code}): ${error.message}`, + [{ + text: 'Dismiss', + onPress: null, + }] + ); + } + + _onRemoteNotification(notification) { AlertIOS.alert( 'Push Notification Received', 'Alert message: ' + notification.getMessage(), @@ -170,8 +194,6 @@ exports.examples = [ { title: 'Badge Number', render(): ReactElement { - PushNotificationIOS.requestPermissions(); - return (