[fcm] Work in progress iOS message support

This commit is contained in:
Chris Bianca 2018-02-02 12:05:51 +00:00
parent 850f04914f
commit a460d8f809
7 changed files with 170 additions and 15 deletions

View File

@ -304,7 +304,7 @@ public class RNFirebaseMessaging extends ReactContextBaseJavaModule implements A
public void onReceive(Context context, Intent intent) {
if (getReactApplicationContext().hasActiveCatalystInstance()) {
String token = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Received new token: " + token);
Log.d(TAG, "Received new FCM token: " + token);
Utils.sendEvent(getReactApplicationContext(), "messaging_token_refreshed", token);
}

View File

@ -10,8 +10,8 @@
+ (FIRApp *)getApp:(NSString *)appDisplayName;
+ (NSString *)getAppName:(NSString *)appDisplayName;
+ (NSString *)getAppDisplayName:(NSString *)appName;
+ (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(NSDictionary *)body;
+ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter app:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body;
+ (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(id)body;
+ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter app:(FIRApp *)app name:(NSString *)name body:(id)body;
@end

View File

@ -24,7 +24,7 @@ static NSString *const DEFAULT_APP_NAME = @"__FIRAPP_DEFAULT";
return appName;
}
+ (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(NSDictionary *)body {
+ (void)sendJSEvent:(RCTEventEmitter *)emitter name:(NSString *)name body:(id)body {
@try {
// TODO: Temporary fix for https://github.com/invertase/react-native-firebase/issues/233
// until a better solution comes around
@ -36,7 +36,7 @@ static NSString *const DEFAULT_APP_NAME = @"__FIRAPP_DEFAULT";
}
}
+ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter app:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body {
+ (void)sendJSEventWithAppName:(RCTEventEmitter *)emitter app:(FIRApp *)app name:(NSString *)name body:(id)body {
// Add the appName to the body
NSMutableDictionary *newBody = [body mutableCopy];
newBody[@"appName"] = [RNFirebaseUtil getAppDisplayName:app.name];

View File

@ -9,8 +9,11 @@
@interface RNFirebaseMessaging : RCTEventEmitter<RCTBridgeModule, FIRMessagingDelegate>
#if !TARGET_OS_TV
+ (_Nonnull instancetype)instance;
#if !TARGET_OS_TV
- (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo;
- (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(void (^_Nonnull)(UIBackgroundFetchResult))completionHandler;
#endif
@end

View File

@ -11,32 +11,155 @@
#import <React/RCTConvert.h>
#import <React/RCTUtils.h>
@interface RNFirebaseMessaging ()
// For iOS 10 we need to implement UNUserNotificationCenterDelegate to receive display
// notifications via APNS
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
@import UserNotifications;
@interface RNFirebaseMessaging () <UNUserNotificationCenterDelegate>
@end
#endif
@implementation RNFirebaseMessaging
static RNFirebaseMessaging *theRNFirebaseMessaging = nil;
+ (nonnull instancetype)instance {
return theRNFirebaseMessaging;
}
RCT_EXPORT_MODULE()
- (id)init {
self = [super init];
if (self != nil) {
NSLog(@"Setting up RNFirebaseMessaging instance");
[self initialiseMessaging];
[self configure];
}
return self;
}
- (void)initialiseMessaging {
- (void)configure {
// Set as delegate for FIRMessaging
[FIRMessaging messaging].delegate = self;
// Establish Firebase managed data channel
[FIRMessaging messaging].shouldEstablishDirectChannel = YES;
// If we're on iOS 10 then we need to set this as a delegate for the UNUserNotificationCenter
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
#endif
// Set static instance for use from AppDelegate
static dispatch_once_t once;
dispatch_once(&once, ^{
theRNFirebaseMessaging = self;
});
}
- (void)dealloc {
}
// ** AppDelegate methods **
// Listen for background messages
- (void)didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo {
BOOL isFromBackground = (RCTSharedApplication().applicationState == UIApplicationStateInactive);
// TODO: Format data before send
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:userInfo];
}
// Listen for background messages
- (void)didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
BOOL isFromBackground = (RCTSharedApplication().applicationState == UIApplicationStateInactive);
// TODO: Format data before send
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:userInfo];
}
// ** UNUserNotificationCenterDelegate methods **
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// Handle incoming notification messages while app is in the foreground.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSDictionary *userInfo = notification.request.content.userInfo;
// TODO: Format data before send
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:userInfo];
// TODO: Change this to your preferred presentation option
completionHandler(UNNotificationPresentationOptionNone);
}
// Handle notification messages after display notification is tapped by the user.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
#if defined(__IPHONE_11_0)
withCompletionHandler:(void(^)(void))completionHandler {
#else
withCompletionHandler:(void(^)())completionHandler {
#endif
NSDictionary *userInfo = response.notification.request.content.userInfo;
// TODO: Format data before send
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:userInfo];
completionHandler();
}
#endif
// ** FIRMessagingDelegate methods **
// Listen for FCM tokens
- (void)messaging:(FIRMessaging *)messaging didReceiveRegistrationToken:(NSString *)fcmToken {
NSLog(@"Received new FCM token: %@", fcmToken);
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_TOKEN_REFRESHED body:fcmToken];
}
// Listen for data messages in the foreground
- (void)applicationReceivedRemoteMessage:(nonnull FIRMessagingRemoteMessage *)remoteMessage {
NSDictionary *appData = remoteMessage.appData;
NSMutableDictionary *message = [[NSMutableDictionary alloc] init];
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
for (id k1 in appData) {
if ([k1 isEqualToString:@"collapse_key"]) {
message[@"collapseKey"] = appData[@"collapse_key"];
} else if ([k1 isEqualToString:@"from"]) {
message[@"from"] = appData[@"from"];
} else if ([k1 isEqualToString:@"notification"]) {
NSDictionary *n = appData[@"notification"];
NSMutableDictionary *notification = [[NSMutableDictionary alloc] init];
for (id k2 in appData[@"notification"]) {
if ([k2 isEqualToString:@"badge"]) {
notification[@"badge"] = n[@"badge"];
} else if ([k2 isEqualToString:@"body"]) {
notification[@"body"] = n[@"body"];
} else if ([k2 isEqualToString:@"sound"]) {
notification[@"sound"] = n[@"sound"];
} else if ([k2 isEqualToString:@"title"]) {
notification[@"title"] = n[@"title"];
} else {
NSLog(@"Unknown notification key: %@", k2);
}
}
message[@"notification"] = notification;
} else {
data[k1] = appData[k1];
}
}
message[@"data"] = data;
message[@"openedFromTray"] = @(false);
[RNFirebaseUtil sendJSEvent:self name:MESSAGING_MESSAGE_RECEIVED body:message];
}
// ** Start React Module methods **
RCT_EXPORT_METHOD(getToken:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
resolve([[FIRInstanceID instanceID] token]);
@ -56,7 +179,6 @@ RCT_EXPORT_METHOD(requestPermission:(RCTPromiseResolveBlock)resolve rejecter:(RC
// TODO: Is there something we can listen for?
resolve(@{@"status":@"unknown"});
} else {
// iOS 10 or later
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
// For iOS 10 display notification (sent via APNS)
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
@ -81,12 +203,12 @@ RCT_EXPORT_METHOD(getBadge: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromise
resolve(@([RCTSharedApplication() applicationIconBadgeNumber]));
}
RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
UILocalNotification *localUserInfo = [self bridge].launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
if (localUserInfo) {
resolve([[localUserInfo userInfo] copy]);
RCT_EXPORT_METHOD(getInitialMessage:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
NSDictionary *notification = [self bridge].launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
if (notification) {
resolve([notification copy]);
} else {
resolve([[self bridge].launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy]);
resolve(nil);
}
}

View File

@ -5,6 +5,25 @@
@implementation RNFirebaseNotifications
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
UILocalNotification *localUserInfo = [self bridge].launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
if (localUserInfo) {
// TODO: Proper format
resolve([[localUserInfo userInfo] copy]);
} else {
resolve(nil);
}
}
- (NSArray<NSString *> *)supportedEvents {
return @[];
}
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
@end
#else

View File

@ -12,12 +12,14 @@
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <Firebase.h>
#import <RNFirebaseMessaging.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FIRApp configure];
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
@ -36,4 +38,13 @@
return YES;
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
[[RNFirebaseMessaging instance] didReceiveRemoteNotification:userInfo];
}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[[RNFirebaseMessaging instance] didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
@end