Skip to content

Commit

Permalink
Fixed incompatibility with cordova-plugin-local-notification@0.9.0-be…
Browse files Browse the repository at this point in the history
…ta.2
  • Loading branch information
andrehtissot committed Jun 7, 2020
1 parent e602729 commit 01f7c2c
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 55 deletions.
3 changes: 3 additions & 0 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
<header-file src="src/ios/FCMPluginIOS9Support.h" />
<source-file src="src/ios/FCMPluginIOS9Support.m" />

<header-file src="src/ios/FCMNotificationCenterDelegate.h" />
<source-file src="src/ios/FCMNotificationCenterDelegate.m" />

<!-- FIREBASE COCOAPODS-->
<podspec>
<config>
Expand Down
63 changes: 8 additions & 55 deletions src/ios/AppDelegate+FCMPlugin.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "AppDelegate+FCMPlugin.h"
#import "FCMPlugin.h"
#import "FCMPluginIOS9Support.h"
#import "FCMNotificationCenterDelegate.h"
#import <objc/runtime.h>
#import <Foundation/Foundation.h>

Expand All @@ -10,7 +11,7 @@
// Implement UNUserNotificationCenterDelegate to receive display notification via APNS for devices
// running iOS 10 and above. Implement FIRMessagingDelegate to receive data message via FCM for
// devices running iOS 10 and above.
@interface AppDelegate () <UNUserNotificationCenterDelegate, FIRMessagingDelegate>
@interface AppDelegate () <FIRMessagingDelegate>
@end

@implementation AppDelegate (MCPlugin)
Expand All @@ -19,6 +20,7 @@ @implementation AppDelegate (MCPlugin)
static NSString *fcmToken;
static NSString *apnsToken;
NSString *const kGCMMessageIDKey = @"gcm.message_id";
FCMNotificationCenterDelegate *notificationCenterDelegate;

//Method swizzling
+ (void)load {
Expand All @@ -31,6 +33,11 @@ - (BOOL)application:(UIApplication *)application customDidFinishLaunchingWithOpt
[self application:application customDidFinishLaunchingWithOptions:launchOptions];

NSLog(@"DidFinishLaunchingWithOptions");
if ([UNUserNotificationCenter class] != nil) {
// For iOS 10 display notification (sent via APNS)
notificationCenterDelegate = [NSClassFromString(@"FCMNotificationCenterDelegate") alloc];
[notificationCenterDelegate configureForNotifications];
}
[self performSelector:@selector(configureForNotifications) withObject:self afterDelay:0.3f];

return YES;
Expand All @@ -40,10 +47,6 @@ - (void)configureForNotifications {
if([FIRApp defaultApp] == nil) {
[FIRApp configure];
}
if ([UNUserNotificationCenter class] != nil) {
// For iOS 10 display notification (sent via APNS)
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
}
// For iOS message (sent via FCM)
[FIRMessaging messaging].delegate = self;
}
Expand All @@ -66,56 +69,6 @@ + (void)requestPushPermission:(void (^)(BOOL yesOrNo, NSError* _Nullable error))
}];
}

// [BEGIN message_handling]
// Handle incoming notification messages while app is in the foreground.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
// Print message ID.
NSDictionary *userInfo = notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey]) {
NSLog(@"Message ID 1: %@", userInfo[kGCMMessageIDKey]);
}

// Print full message.
NSLog(@"%@", userInfo);

NSError *error;
NSDictionary *userInfoMutable = [userInfo mutableCopy];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userInfoMutable
options:0
error:&error];
[FCMPlugin.fcmPlugin notifyOfMessage:jsonData];

// 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
withCompletionHandler:(void (^)(void))completionHandler {
NSDictionary *userInfo = response.notification.request.content.userInfo;
if (userInfo[kGCMMessageIDKey]) {
NSLog(@"Message ID 2: %@", userInfo[kGCMMessageIDKey]);
}

// Print full message.
NSLog(@"%@", userInfo);

NSError *error;
NSDictionary *userInfoMutable = [userInfo mutableCopy];

NSLog(@"New method with push callback: %@", userInfo);

[userInfoMutable setValue:@(YES) forKey:@"wasTapped"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userInfoMutable options:0 error:&error];
NSLog(@"APP WAS CLOSED DURING PUSH RECEPTION Saved data: %@", jsonData);
lastPush = jsonData;

completionHandler();
}

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceTokenData {
[FIRMessaging messaging].APNSToken = deviceTokenData;
NSString *deviceToken;
Expand Down
7 changes: 7 additions & 0 deletions src/ios/FCMNotificationCenterDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#import <UIKit/UIKit.h>

@interface FCMNotificationCenterDelegate : NSObject {}

- (void)configureForNotifications;

@end
129 changes: 129 additions & 0 deletions src/ios/FCMNotificationCenterDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#import "AppDelegate+FCMPlugin.h"
#import "FCMPlugin.h"
#import "FCMNotificationCenterDelegate.h"
#import <objc/runtime.h>
#import <Foundation/Foundation.h>

@import UserNotifications;

// Implement UNUserNotificationCenterDelegate to receive display notification via APNS for devices
// running iOS 10 and above.
@interface FCMNotificationCenterDelegate () <UNUserNotificationCenterDelegate>
@end

@implementation FCMNotificationCenterDelegate

NSMutableArray<NSObject<UNUserNotificationCenterDelegate>*> *subNotificationCenterDelegates;

- (void) forceNotificationCenterDelegate:(float)timeout {
[self setNotificationCenterDelegate];
if(timeout < 0) {
// The job should be done.
return;
}
SEL thisMethodSelector = NSSelectorFromString(@"forceNotificationCenterDelegate:");
if([self respondsToSelector:thisMethodSelector]) {
// NSLog(@"FCMNotificationCenterDelegate found: %@", [UNUserNotificationCenter currentNotificationCenter].delegate);
float remainingTimeout = timeout - 0.1f;
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:thisMethodSelector]];
[invocation setSelector:thisMethodSelector];
[invocation setTarget:self];
[invocation setArgument:&(remainingTimeout) atIndex:2];
[NSTimer scheduledTimerWithTimeInterval:0.1f invocation:invocation repeats:NO];
return;
}
NSLog(@"forceNotificationCenterDelegate selector not found in FCMNotificationCenterDelegate");
}

- (void)configureForNotifications {
subNotificationCenterDelegates = [[NSMutableArray alloc]initWithCapacity:0];
[self setNotificationCenterDelegate];
[self forceNotificationCenterDelegate:10];
}

- (void) setNotificationCenterDelegate {
if([UNUserNotificationCenter currentNotificationCenter].delegate == self) {
return;
}
if([UNUserNotificationCenter currentNotificationCenter].delegate != nil) {
[subNotificationCenterDelegates addObject:[UNUserNotificationCenter currentNotificationCenter].delegate];
// NSLog(@"subNotificationCenterDelegates: %@", subNotificationCenterDelegates);
}
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
}


// 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;

// Print full message.
NSLog(@"willPresentNotification: %@", userInfo);

NSError *error;
NSDictionary *userInfoMutable = [userInfo mutableCopy];
[userInfoMutable setValue:@(NO) forKey:@"wasTapped"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userInfoMutable
options:0
error:&error];
[FCMPlugin.fcmPlugin notifyOfMessage:jsonData];

if(subNotificationCenterDelegates.count == 0){
// No subNotificationCenterDelegates to work with
// Change this to your preferred presentation option
completionHandler(UNNotificationPresentationOptionNone);
}

// Change this to your preferred presentation option
__block UNNotificationPresentationOptions notificationPresentationOptions = UNNotificationPresentationOptionNone;
void (^subDelegateCompletionHandler)(UNNotificationPresentationOptions) = ^(UNNotificationPresentationOptions possibleNotificationPresentationOptions)
{
if(notificationPresentationOptions < possibleNotificationPresentationOptions) {
notificationPresentationOptions = possibleNotificationPresentationOptions;
}
};
SEL thisMethodSelector = NSSelectorFromString(@"userNotificationCenter:willPresentNotification:withCompletionHandler:");
for (NSObject<UNUserNotificationCenterDelegate>* subNotificationCenterDelegate in subNotificationCenterDelegates) {
if([subNotificationCenterDelegate respondsToSelector:thisMethodSelector]) {
[subNotificationCenterDelegate userNotificationCenter:center willPresentNotification:notification withCompletionHandler:subDelegateCompletionHandler];
// } else {
// NSLog(@"subNotificationCenterDelegates[i] not found willPresentNotification: %@", subNotificationCenterDelegate );
}
}

completionHandler(notificationPresentationOptions);
}

// Handle notification messages after display notification is tapped by the user.
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler {
NSDictionary *userInfo = response.notification.request.content.userInfo;

// Print full message.
NSLog(@"didReceiveNotificationResponse: %@", userInfo);

NSError *error;
NSDictionary *userInfoMutable = [userInfo mutableCopy];
[userInfoMutable setValue:@(YES) forKey:@"wasTapped"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userInfoMutable options:0 error:&error];
[AppDelegate setLastPush:jsonData];

if(subNotificationCenterDelegates.count == 0){
// No subNotificationCenterDelegates to work with
completionHandler();
}

void (^noopCompletionHandler)(void) = ^(){};
SEL thisMethodSelector = NSSelectorFromString(@"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:");
for (NSObject<UNUserNotificationCenterDelegate>* subNotificationCenterDelegate in subNotificationCenterDelegates) {
if([subNotificationCenterDelegate respondsToSelector:thisMethodSelector]) {
[subNotificationCenterDelegate userNotificationCenter:center didReceiveNotificationResponse:response withCompletionHandler:noopCompletionHandler];
}
}
completionHandler();
}

@end

0 comments on commit 01f7c2c

Please sign in to comment.