registration error event
Summary: This is an updated version of #2336 and #7694. --- This adds a `registrationError` event that is emitted by `PushNotificationIOS` whenever an application receives a registration error from APNS (APNS service failure, running on simulator, etc). This event fires to the exclusion of the `register` event (and vice versa). **How to use** Add the following to your `AppDelegate.m`: ```obj-c - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { [RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error]; } ``` And register an event handler for the event: ```js PushNotificationIOS.addEventListener('registrationError', function({ message, code }) { // Complete your registration process in error. }); ``` **Test plan** Added support for this event (and `register`) to UIExplorer as a proof of concept. Navigating to the push notifications example on a simulator is an easy way to reproduce this e Closes https://github.com/facebook/react-native/pull/9650 Differential Revision: D3822142 Pulled By: javache fbshipit-source-id: a15ed8941b74dc3eed2c44c658deccbcaf39ce3d
This commit is contained in:
parent
dea6b0e24c
commit
4f89fa9cf3
|
@ -19,6 +19,7 @@
|
||||||
#import "RCTJavaScriptLoader.h"
|
#import "RCTJavaScriptLoader.h"
|
||||||
#import "RCTLinkingManager.h"
|
#import "RCTLinkingManager.h"
|
||||||
#import "RCTRootView.h"
|
#import "RCTRootView.h"
|
||||||
|
#import "RCTPushNotificationManager.h"
|
||||||
|
|
||||||
@interface AppDelegate() <RCTBridgeDelegate>
|
@interface AppDelegate() <RCTBridgeDelegate>
|
||||||
|
|
||||||
|
@ -76,4 +77,36 @@
|
||||||
onComplete:loadCallback];
|
onComplete:loadCallback];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# pragma mark - Push Notifications
|
||||||
|
|
||||||
|
// Required to register for notifications
|
||||||
|
- (void)application:(__unused UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
|
||||||
|
{
|
||||||
|
[RCTPushNotificationManager didRegisterUserNotificationSettings:notificationSettings];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required for the remoteNotificationsRegistered event.
|
||||||
|
- (void)application:(__unused UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
||||||
|
{
|
||||||
|
[RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required for the remoteNotificationRegistrationError event.
|
||||||
|
- (void)application:(__unused UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
|
||||||
|
{
|
||||||
|
[RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required for the remoteNotificationReceived event.
|
||||||
|
- (void)application:(__unused UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification
|
||||||
|
{
|
||||||
|
[RCTPushNotificationManager didReceiveRemoteNotification:notification];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required for the localNotificationReceived event.
|
||||||
|
- (void)application:(__unused UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
|
||||||
|
{
|
||||||
|
[RCTPushNotificationManager didReceiveLocalNotification:notification];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -50,16 +50,18 @@ class Button extends React.Component {
|
||||||
|
|
||||||
class NotificationExample extends React.Component {
|
class NotificationExample extends React.Component {
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
// Add listener for push notifications
|
PushNotificationIOS.addEventListener('register', this._onRegistered);
|
||||||
PushNotificationIOS.addEventListener('notification', this._onNotification);
|
PushNotificationIOS.addEventListener('registrationError', this._onRegistrationError);
|
||||||
// Add listener for local notifications
|
PushNotificationIOS.addEventListener('notification', this._onRemoteNotification);
|
||||||
PushNotificationIOS.addEventListener('localNotification', this._onLocalNotification);
|
PushNotificationIOS.addEventListener('localNotification', this._onLocalNotification);
|
||||||
|
|
||||||
|
PushNotificationIOS.requestPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
// Remove listener for push notifications
|
PushNotificationIOS.removeEventListener('register', this._onRegistered);
|
||||||
PushNotificationIOS.removeEventListener('notification', this._onNotification);
|
PushNotificationIOS.removeEventListener('registrationError', this._onRegistrationError);
|
||||||
// Remove listener for local notifications
|
PushNotificationIOS.removeEventListener('notification', this._onRemoteNotification);
|
||||||
PushNotificationIOS.removeEventListener('localNotification', this._onLocalNotification);
|
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(
|
AlertIOS.alert(
|
||||||
'Push Notification Received',
|
'Push Notification Received',
|
||||||
'Alert message: ' + notification.getMessage(),
|
'Alert message: ' + notification.getMessage(),
|
||||||
|
@ -170,8 +194,6 @@ exports.examples = [
|
||||||
{
|
{
|
||||||
title: 'Badge Number',
|
title: 'Badge Number',
|
||||||
render(): ReactElement<any> {
|
render(): ReactElement<any> {
|
||||||
PushNotificationIOS.requestPermissions();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -21,8 +21,36 @@ const _notifHandlers = new Map();
|
||||||
|
|
||||||
const DEVICE_NOTIF_EVENT = 'remoteNotificationReceived';
|
const DEVICE_NOTIF_EVENT = 'remoteNotificationReceived';
|
||||||
const NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered';
|
const NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered';
|
||||||
|
const NOTIF_REGISTRATION_ERROR_EVENT = 'remoteNotificationRegistrationError';
|
||||||
const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived';
|
const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event emitted by PushNotificationIOS.
|
||||||
|
*/
|
||||||
|
export type PushNotificationEventName = $Enum<{
|
||||||
|
/**
|
||||||
|
* Fired when a remote notification is received. The handler will be invoked
|
||||||
|
* with an instance of `PushNotificationIOS`.
|
||||||
|
*/
|
||||||
|
notification: string,
|
||||||
|
/**
|
||||||
|
* Fired when a local notification is received. The handler will be invoked
|
||||||
|
* with an instance of `PushNotificationIOS`.
|
||||||
|
*/
|
||||||
|
localNotification: string,
|
||||||
|
/**
|
||||||
|
* Fired when the user registers for remote notifications. The handler will be
|
||||||
|
* invoked with a hex string representing the deviceToken.
|
||||||
|
*/
|
||||||
|
register: string,
|
||||||
|
/**
|
||||||
|
* Fired when the user fails to register for remote notifications. Typically
|
||||||
|
* occurs when APNS is having issues, or the device is a simulator. The
|
||||||
|
* handler will be invoked with {message: string, code: number, details: any}.
|
||||||
|
*/
|
||||||
|
registrationError: string,
|
||||||
|
}>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle push notifications for your app, including permission handling and
|
* Handle push notifications for your app, including permission handling and
|
||||||
* icon badge number.
|
* icon badge number.
|
||||||
|
@ -56,6 +84,11 @@ const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived';
|
||||||
* {
|
* {
|
||||||
* [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
|
* [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
|
||||||
* }
|
* }
|
||||||
|
* // Required for the registrationError event.
|
||||||
|
* - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
|
||||||
|
* {
|
||||||
|
* [RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error];
|
||||||
|
* }
|
||||||
* // Required for the notification event.
|
* // Required for the notification event.
|
||||||
* - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification
|
* - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification
|
||||||
* {
|
* {
|
||||||
|
@ -66,10 +99,6 @@ const DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived';
|
||||||
* {
|
* {
|
||||||
* [RCTPushNotificationManager didReceiveLocalNotification:notification];
|
* [RCTPushNotificationManager didReceiveLocalNotification:notification];
|
||||||
* }
|
* }
|
||||||
* - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
|
|
||||||
* {
|
|
||||||
* NSLog(@"%@", error);
|
|
||||||
* }
|
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class PushNotificationIOS {
|
class PushNotificationIOS {
|
||||||
|
@ -162,11 +191,15 @@ class PushNotificationIOS {
|
||||||
* handler will be invoked with an instance of `PushNotificationIOS`.
|
* handler will be invoked with an instance of `PushNotificationIOS`.
|
||||||
* - `register`: Fired when the user registers for remote notifications. The
|
* - `register`: Fired when the user registers for remote notifications. The
|
||||||
* handler will be invoked with a hex string representing the deviceToken.
|
* handler will be invoked with a hex string representing the deviceToken.
|
||||||
|
* - `registrationError`: Fired when the user fails to register for remote
|
||||||
|
* notifications. Typically occurs when APNS is having issues, or the device
|
||||||
|
* is a simulator. The handler will be invoked with
|
||||||
|
* {message: string, code: number, details: any}.
|
||||||
*/
|
*/
|
||||||
static addEventListener(type: string, handler: Function) {
|
static addEventListener(type: PushNotificationEventName, handler: Function) {
|
||||||
invariant(
|
invariant(
|
||||||
type === 'notification' || type === 'register' || type === 'localNotification',
|
type === 'notification' || type === 'register' || type === 'registrationError' || type === 'localNotification',
|
||||||
'PushNotificationIOS only supports `notification`, `register` and `localNotification` events'
|
'PushNotificationIOS only supports `notification`, `register`, `registrationError`, and `localNotification` events'
|
||||||
);
|
);
|
||||||
var listener;
|
var listener;
|
||||||
if (type === 'notification') {
|
if (type === 'notification') {
|
||||||
|
@ -190,6 +223,13 @@ class PushNotificationIOS {
|
||||||
handler(registrationInfo.deviceToken);
|
handler(registrationInfo.deviceToken);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else if (type === 'registrationError') {
|
||||||
|
listener = PushNotificationEmitter.addListener(
|
||||||
|
NOTIF_REGISTRATION_ERROR_EVENT,
|
||||||
|
(errorInfo) => {
|
||||||
|
handler(errorInfo);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_notifHandlers.set(handler, listener);
|
_notifHandlers.set(handler, listener);
|
||||||
}
|
}
|
||||||
|
@ -198,10 +238,10 @@ class PushNotificationIOS {
|
||||||
* Removes the event listener. Do this in `componentWillUnmount` to prevent
|
* Removes the event listener. Do this in `componentWillUnmount` to prevent
|
||||||
* memory leaks
|
* memory leaks
|
||||||
*/
|
*/
|
||||||
static removeEventListener(type: string, handler: Function) {
|
static removeEventListener(type: PushNotificationEventName, handler: Function) {
|
||||||
invariant(
|
invariant(
|
||||||
type === 'notification' || type === 'register' || type === 'localNotification',
|
type === 'notification' || type === 'register' || type === 'registrationError' || type === 'localNotification',
|
||||||
'PushNotificationIOS only supports `notification`, `register` and `localNotification` events'
|
'PushNotificationIOS only supports `notification`, `register`, `registrationError`, and `localNotification` events'
|
||||||
);
|
);
|
||||||
var listener = _notifHandlers.get(handler);
|
var listener = _notifHandlers.get(handler);
|
||||||
if (!listener) {
|
if (!listener) {
|
||||||
|
|
|
@ -15,5 +15,6 @@
|
||||||
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
|
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
|
||||||
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification;
|
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification;
|
||||||
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification;
|
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification;
|
||||||
|
+ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -20,6 +20,7 @@ NSString *const RCTRemoteNotificationsRegistered = @"RemoteNotificationsRegister
|
||||||
NSString *const RCTRegisterUserNotificationSettings = @"RegisterUserNotificationSettings";
|
NSString *const RCTRegisterUserNotificationSettings = @"RegisterUserNotificationSettings";
|
||||||
|
|
||||||
NSString *const RCTErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS";
|
NSString *const RCTErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS";
|
||||||
|
NSString *const RCTErrorRemoteNotificationRegistrationFailed = @"E_FAILED_TO_REGISTER_FOR_REMOTE_NOTIFICATIONS";
|
||||||
|
|
||||||
@implementation RCTConvert (UILocalNotification)
|
@implementation RCTConvert (UILocalNotification)
|
||||||
|
|
||||||
|
@ -86,6 +87,10 @@ RCT_EXPORT_MODULE()
|
||||||
selector:@selector(handleRemoteNotificationsRegistered:)
|
selector:@selector(handleRemoteNotificationsRegistered:)
|
||||||
name:RCTRemoteNotificationsRegistered
|
name:RCTRemoteNotificationsRegistered
|
||||||
object:nil];
|
object:nil];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(handleRemoteNotificationRegistrationError:)
|
||||||
|
name:RCTErrorRemoteNotificationRegistrationFailed
|
||||||
|
object:nil];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
selector:@selector(handleRegisterUserNotificationSettings:)
|
selector:@selector(handleRegisterUserNotificationSettings:)
|
||||||
name:RCTRegisterUserNotificationSettings
|
name:RCTRegisterUserNotificationSettings
|
||||||
|
@ -101,7 +106,8 @@ RCT_EXPORT_MODULE()
|
||||||
{
|
{
|
||||||
return @[@"localNotificationReceived",
|
return @[@"localNotificationReceived",
|
||||||
@"remoteNotificationReceived",
|
@"remoteNotificationReceived",
|
||||||
@"remoteNotificationsRegistered"];
|
@"remoteNotificationsRegistered",
|
||||||
|
@"remoteNotificationRegistrationError"];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings *)notificationSettings
|
+ (void)didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings *)notificationSettings
|
||||||
|
@ -127,6 +133,13 @@ RCT_EXPORT_MODULE()
|
||||||
userInfo:@{@"deviceToken" : [hexString copy]}];
|
userInfo:@{@"deviceToken" : [hexString copy]}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTErrorRemoteNotificationRegistrationFailed
|
||||||
|
object:self
|
||||||
|
userInfo:@{@"error": error}];
|
||||||
|
}
|
||||||
|
|
||||||
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
|
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
|
||||||
{
|
{
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
|
||||||
|
@ -158,6 +171,17 @@ RCT_EXPORT_MODULE()
|
||||||
[self sendEventWithName:@"remoteNotificationsRegistered" body:notification.userInfo];
|
[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
|
- (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
if (_requestPermissionsResolveBlock == nil) {
|
if (_requestPermissionsResolveBlock == nil) {
|
||||||
|
|
Loading…
Reference in New Issue