[ios][notifications] Handle messaging token refreshed before bridge initialised #960

This commit is contained in:
Chris Bianca 2018-04-13 14:22:17 +01:00
parent 93b4e3e052
commit 3a5686c226
2 changed files with 41 additions and 10 deletions

View File

@ -18,6 +18,8 @@
@implementation RNFirebaseMessaging @implementation RNFirebaseMessaging
static RNFirebaseMessaging *theRNFirebaseMessaging = nil; static RNFirebaseMessaging *theRNFirebaseMessaging = nil;
static bool jsReady = FALSE;
static NSString* initialToken = nil;
+ (nonnull instancetype)instance { + (nonnull instancetype)instance {
return theRNFirebaseMessaging; return theRNFirebaseMessaging;
@ -66,7 +68,7 @@ RCT_EXPORT_MODULE()
// Listen for FCM data messages that arrive as a remote notification // Listen for FCM data messages that arrive as a remote notification
- (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo { - (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
NSDictionary *message = [self parseUserInfo:userInfo]; NSDictionary *message = [self parseUserInfo:userInfo];
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:message]; [self sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:message];
} }
// ******************************************************* // *******************************************************
@ -82,13 +84,13 @@ RCT_EXPORT_MODULE()
// Listen for FCM tokens // Listen for FCM tokens
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken { - (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
NSLog(@"Received new FCM token: %@", fcmToken); NSLog(@"Received new FCM token: %@", fcmToken);
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_TOKEN_REFRESHED body:fcmToken]; [self sendJSEvent:self name:MESSAGING_TOKEN_REFRESHED body:fcmToken];
} }
// Listen for data messages in the foreground // Listen for data messages in the foreground
- (void)applicationReceivedRemoteMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage { - (void)applicationReceivedRemoteMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage {
NSDictionary *message = [self parseFIRMessagingRemoteMessage:remoteMessage]; NSDictionary *message = [self parseFIRMessagingRemoteMessage:remoteMessage];
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:message]; [self sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:message];
} }
// Receive data messages on iOS 10+ directly from FCM (bypassing APNs) when the app is in the foreground. // Receive data messages on iOS 10+ directly from FCM (bypassing APNs) when the app is in the foreground.
@ -96,7 +98,7 @@ RCT_EXPORT_MODULE()
- (void)messaging:(nonnull FIRMessaging *)messaging - (void)messaging:(nonnull FIRMessaging *)messaging
didReceiveMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage { didReceiveMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage {
NSDictionary *message = [self parseFIRMessagingRemoteMessage:remoteMessage]; NSDictionary *message = [self parseFIRMessagingRemoteMessage:remoteMessage];
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:message]; [self sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:message];
} }
// ******************************************************* // *******************************************************
@ -120,11 +122,11 @@ RCT_EXPORT_METHOD(requestPermission:(RCTPromiseResolveBlock)resolve rejecter:(RC
[RCTSharedApplication() registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:types categories:nil]]; [RCTSharedApplication() registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:types categories:nil]];
// We set the promise for usage by the AppDelegate callback which listens // We set the promise for usage by the AppDelegate callback which listens
// for the result of the permission request // for the result of the permission request
_permissionRejecter = reject; self.permissionRejecter = reject;
_permissionResolver = resolve; self.permissionResolver = resolve;
}); });
} else { } else {
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 if (@available(iOS 10.0, *)) {
// For iOS 10 display notification (sent via APNS) // For iOS 10 display notification (sent via APNS)
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge; UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) { [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
@ -134,7 +136,7 @@ RCT_EXPORT_METHOD(requestPermission:(RCTPromiseResolveBlock)resolve rejecter:(RC
reject(@"messaging/permission_error", @"Failed to grant permission", error); reject(@"messaging/permission_error", @"Failed to grant permission", error);
} }
}]; }];
#endif }
} }
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
@ -149,11 +151,11 @@ RCT_EXPORT_METHOD(hasPermission:(RCTPromiseResolveBlock)resolve rejecter:(RCTPro
resolve(@([RCTSharedApplication() currentUserNotificationSettings].types != UIUserNotificationTypeNone)); resolve(@([RCTSharedApplication() currentUserNotificationSettings].types != UIUserNotificationTypeNone));
}); });
} else { } else {
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 if (@available(iOS 10.0, *)) {
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) { [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
resolve(@(settings.alertSetting == UNNotificationSettingEnabled)); resolve(@(settings.alertSetting == UNNotificationSettingEnabled));
}]; }];
#endif }
} }
} }
@ -189,8 +191,31 @@ RCT_EXPORT_METHOD(unsubscribeFromTopic: (NSString*) topic
resolve(nil); resolve(nil);
} }
RCT_EXPORT_METHOD(jsInitialised:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
jsReady = TRUE;
resolve(nil);
if (initialToken) {
[self sendJSEvent:self name:MESSAGING_TOKEN_REFRESHED body:initialToken];
}
}
// ** Start internals ** // ** Start internals **
// Because of the time delay between the app starting and the bridge being initialised
// we catch any events that are received before the JS is ready to receive them
- (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(id)body {
if (emitter.bridge && jsReady) {
[RNFirebaseUtil sendJSEvent:emitter name:name body:body];
} else {
if ([name isEqualToString:MESSAGING_TOKEN_REFRESHED]) {
initialToken = body;
} else {
// TODO: Is this even possible?
NSLog(@"Received Remote Message before the bridge is ready");
}
}
}
- (NSDictionary*)parseFIRMessagingRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage { - (NSDictionary*)parseFIRMessagingRemoteMessage:(FIRMessagingRemoteMessage *)remoteMessage {
NSDictionary *appData = remoteMessage.appData; NSDictionary *appData = remoteMessage.appData;

View File

@ -2,6 +2,7 @@
* @flow * @flow
* Messaging (FCM) representation wrapper * Messaging (FCM) representation wrapper
*/ */
import { Platform } from 'react-native';
import { SharedEventEmitter } from '../../utils/events'; import { SharedEventEmitter } from '../../utils/events';
import INTERNALS from '../../utils/internals'; import INTERNALS from '../../utils/internals';
import { getLogger } from '../../utils/log'; import { getLogger } from '../../utils/log';
@ -63,6 +64,11 @@ export default class Messaging extends ModuleBase {
SharedEventEmitter.emit('onTokenRefresh', token); SharedEventEmitter.emit('onTokenRefresh', token);
} }
); );
// Tell the native module that we're ready to receive events
if (Platform.OS === 'ios') {
getNativeModule(this).jsInitialised();
}
} }
getToken(): Promise<string> { getToken(): Promise<string> {