From df94ff65bb0671bdab765adb12c29140b518ab82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Tissot?= Date: Sun, 26 Apr 2020 18:57:57 +0200 Subject: [PATCH 1/3] Implemented iOS 9 support for requestPushPermission and hasPushPermission. --- plugin.xml | 3 ++ src/ios/AppDelegate+FCMPlugin.h | 8 ---- src/ios/AppDelegate+FCMPlugin.m | 19 ++++++--- src/ios/FCMPluginIOS9Support.h | 8 ++++ src/ios/FCMPluginIOS9Support.m | 74 +++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 src/ios/FCMPluginIOS9Support.h create mode 100644 src/ios/FCMPluginIOS9Support.m diff --git a/plugin.xml b/plugin.xml index af2cfdf60..dffcee53c 100644 --- a/plugin.xml +++ b/plugin.xml @@ -107,6 +107,9 @@ + + + diff --git a/src/ios/AppDelegate+FCMPlugin.h b/src/ios/AppDelegate+FCMPlugin.h index f37322e59..484f30a3a 100644 --- a/src/ios/AppDelegate+FCMPlugin.h +++ b/src/ios/AppDelegate+FCMPlugin.h @@ -1,11 +1,3 @@ -// -// AppDelegate+FCMPlugin.h -// TestApp -// -// Created by felipe on 12/06/16. -// -// - #import "AppDelegate.h" #import #import diff --git a/src/ios/AppDelegate+FCMPlugin.m b/src/ios/AppDelegate+FCMPlugin.m index 9421cfb5a..a81435ce5 100644 --- a/src/ios/AppDelegate+FCMPlugin.m +++ b/src/ios/AppDelegate+FCMPlugin.m @@ -1,5 +1,6 @@ #import "AppDelegate+FCMPlugin.h" #import "FCMPlugin.h" +#import "FCMPluginIOS9Support.h" #import #import @@ -39,13 +40,18 @@ - (void)configureForNotifications { if([FIRApp defaultApp] == nil) { [FIRApp configure]; } - // For iOS 10 display notification (sent via APNS) - [UNUserNotificationCenter currentNotificationCenter].delegate = self; - // For iOS 10 data message (sent via FCM) + 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; } + (void)requestPushPermission { + if ([UNUserNotificationCenter class] == nil) { + return [FCMPluginIOS9Support requestPushPermission]; + } UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge; [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted) { @@ -168,8 +174,7 @@ - (void)connectToFcm { } // [END connect_to_fcm] -- (void)applicationDidBecomeActive:(UIApplication *)application -{ +- (void)applicationDidBecomeActive:(UIApplication *)application { NSLog(@"app become active"); [FCMPlugin.fcmPlugin appEnterForeground]; [self connectToFcm]; @@ -198,6 +203,10 @@ + (NSString*)getAPNSToken { } + (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block { + if ([UNUserNotificationCenter class] == nil) { + [FCMPluginIOS9Support hasPushPermission:block]; + return; + } UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *settings){ switch (settings.authorizationStatus) { diff --git a/src/ios/FCMPluginIOS9Support.h b/src/ios/FCMPluginIOS9Support.h new file mode 100644 index 000000000..5cfbee07b --- /dev/null +++ b/src/ios/FCMPluginIOS9Support.h @@ -0,0 +1,8 @@ +@interface FCMPluginIOS9Support : NSObject +{ +} + ++ (void)requestPushPermission; ++ (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block; + +@end diff --git a/src/ios/FCMPluginIOS9Support.m b/src/ios/FCMPluginIOS9Support.m new file mode 100644 index 000000000..cadcc8aa2 --- /dev/null +++ b/src/ios/FCMPluginIOS9Support.m @@ -0,0 +1,74 @@ +#import +#import +#import "FCMPluginIOS9Support.h" +#import "AppDelegate+FCMPlugin.h" + +@interface FCMPluginIOS9Support () {} +@end + +@implementation FCMPluginIOS9Support + +NSString *const hasRequestedPushPermissionPersistenceKey = @"FCMPlugin.iOS9.hasRequestedPushPermission"; + ++ (void)requestPushPermission { + UIUserNotificationType allNotificationTypes = + (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge); + UIUserNotificationSettings *settings = + [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil]; + [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[UIApplication sharedApplication] registerForRemoteNotifications]; + [self setHasRequestedPushPermissionWithTimeout:10.0f]; + }); +} + ++ (void)setHasRequestedPushPermissionWithTimeout:(float) timeout { + [self hasPushPermission:^(NSNumber* pushPermission){ + float tryInterval = 0.3f; + if (timeout > 0 && (pushPermission == nil || [pushPermission boolValue] == NO)) { + float remainingTimeout = timeout - tryInterval; + SEL thisMethodSelector = NSSelectorFromString(@"setHasRequestedPushPermissionWithTimeout:"); + if([self respondsToSelector:thisMethodSelector]) { + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:thisMethodSelector]]; + [invocation setSelector:thisMethodSelector]; + [invocation setTarget:self]; + [invocation setArgument:&(remainingTimeout) atIndex:2]; //arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocationion + [NSTimer scheduledTimerWithTimeInterval:tryInterval invocation:invocation repeats:NO]; + return; + } + } + [[NSUserDefaults standardUserDefaults] + setObject:[NSNumber numberWithBool:YES] forKey:hasRequestedPushPermissionPersistenceKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + }]; +} + ++ (BOOL)getHasRequestedPushPermission { + if ([[NSUserDefaults standardUserDefaults] objectForKey:hasRequestedPushPermissionPersistenceKey]) { + bool hasRequestedPushPermission = [[[NSUserDefaults standardUserDefaults] + objectForKey:hasRequestedPushPermissionPersistenceKey] boolValue]; + return hasRequestedPushPermission; + } + return NO; +} + ++ (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block { + NSString* apnsToken = [AppDelegate getAPNSToken]; + if(apnsToken != nil) { + block([NSNumber numberWithBool:YES]); + return; + } + if ([[UIApplication sharedApplication] isRegisteredForRemoteNotifications]) { + block([NSNumber numberWithBool:YES]); + return; + } + UIUserNotificationSettings *notificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings]; + BOOL itDoesHaveNotificationSettings = ((int) notificationSettings.types) != 0; + if(itDoesHaveNotificationSettings) { + block([NSNumber numberWithBool:YES]); + } + BOOL alreadyRequested = [self getHasRequestedPushPermission]; + block(alreadyRequested ? [NSNumber numberWithBool:NO] : nil); +} + +@end From 56c06d6fe5c14d3e1898e463ff17a9a2d8ce2fe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Tissot?= Date: Sun, 26 Apr 2020 19:51:59 +0200 Subject: [PATCH 2/3] Implemented iOS 9 support for didReceiveRemoteNotification --- src/ios/AppDelegate+FCMPlugin.h | 1 + src/ios/AppDelegate+FCMPlugin.m | 43 ++++++++++++++++++++++----------- src/ios/FCMPluginIOS9Support.h | 2 ++ src/ios/FCMPluginIOS9Support.m | 36 +++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/ios/AppDelegate+FCMPlugin.h b/src/ios/AppDelegate+FCMPlugin.h index 484f30a3a..b3cbf35f3 100644 --- a/src/ios/AppDelegate+FCMPlugin.h +++ b/src/ios/AppDelegate+FCMPlugin.h @@ -7,6 +7,7 @@ + (NSData*)getLastPush; + (NSString*)getFCMToken; + (NSString*)getAPNSToken; ++ (void)setLastPush:(NSData*)push; + (void)requestPushPermission; + (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block; diff --git a/src/ios/AppDelegate+FCMPlugin.m b/src/ios/AppDelegate+FCMPlugin.m index a81435ce5..aca7a7360 100644 --- a/src/ios/AppDelegate+FCMPlugin.m +++ b/src/ios/AppDelegate+FCMPlugin.m @@ -129,28 +129,39 @@ - (void)application:(UIApplication *)application didRegisterForRemoteNotificatio NSLog(@"Device APNS Token: %@", deviceToken); } +- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { + if (@available(iOS 10, *)) { + return; + } + [FCMPluginIOS9Support application:application didReceiveRemoteNotification:userInfo]; +} + - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; - - // Print message ID. - NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]); - // Pring full message. - NSLog(@"%@", userInfo); + if (@available(iOS 10, *)) { + // Print message ID. + NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]); - // If the app is in the background, keep it for later, in case it's not tapped. - if(application.applicationState == UIApplicationStateBackground) { - NSError *error; - NSDictionary *userInfoMutable = [userInfo mutableCopy]; - [userInfoMutable setValue:@(NO) forKey:@"wasTapped"]; - NSLog(@"app active"); - lastPush = [NSJSONSerialization dataWithJSONObject:userInfoMutable options:0 error:&error]; + // Pring full message. + NSLog(@"%@", userInfo); + + // If the app is in the background, keep it for later, in case it's not tapped. + if(application.applicationState == UIApplicationStateBackground) { + NSError *error; + NSDictionary *userInfoMutable = [userInfo mutableCopy]; + [userInfoMutable setValue:@(NO) forKey:@"wasTapped"]; + NSLog(@"app active"); + lastPush = [NSJSONSerialization dataWithJSONObject:userInfoMutable options:0 error:&error]; + } + + completionHandler(UIBackgroundFetchResultNoData); + return; } - completionHandler(UIBackgroundFetchResultNoData); + [FCMPluginIOS9Support application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; } -// [END receive_message iOS < 10] // [END message_handling] - (void)messaging:(nonnull FIRMessaging *)messaging didReceiveRegistrationToken:(nonnull NSString *)deviceToken { @@ -188,6 +199,10 @@ - (void)applicationDidEnterBackground:(UIApplication *)application { } // [END disconnect_from_fcm] ++ (void)setLastPush:(NSData*)push { + lastPush = push; +} + + (NSData*)getLastPush { NSData* returnValue = lastPush; lastPush = nil; diff --git a/src/ios/FCMPluginIOS9Support.h b/src/ios/FCMPluginIOS9Support.h index 5cfbee07b..bc54d64d9 100644 --- a/src/ios/FCMPluginIOS9Support.h +++ b/src/ios/FCMPluginIOS9Support.h @@ -4,5 +4,7 @@ + (void)requestPushPermission; + (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block; ++ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo; ++ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler; @end diff --git a/src/ios/FCMPluginIOS9Support.m b/src/ios/FCMPluginIOS9Support.m index cadcc8aa2..3a6ad1af9 100644 --- a/src/ios/FCMPluginIOS9Support.m +++ b/src/ios/FCMPluginIOS9Support.m @@ -1,5 +1,6 @@ #import #import +#import "FCMPlugin.h" #import "FCMPluginIOS9Support.h" #import "AppDelegate+FCMPlugin.h" @@ -71,4 +72,39 @@ + (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block { block(alreadyRequested ? [NSNumber numberWithBool:NO] : nil); } ++ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { + NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]); + NSError *error; + NSDictionary *userInfoMutable = [userInfo mutableCopy]; + if (application.applicationState != UIApplicationStateActive) { + 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); + [AppDelegate setLastPush:jsonData]; + } +} + ++ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { + NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]); + NSLog(@"%@", userInfo); + NSError *error; + NSDictionary *userInfoMutable = [userInfo mutableCopy]; + + // Has user tapped the notificaiton? + // UIApplicationStateActive - app is currently active + // UIApplicationStateInactive - app is transitioning from background to + // foreground (user taps notification) + if (application.applicationState == UIApplicationStateActive + || application.applicationState == UIApplicationStateInactive) { + [userInfoMutable setValue:@(NO) forKey:@"wasTapped"]; + NSLog(@"app active"); + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userInfoMutable + options:0 + error:&error]; + [FCMPlugin.fcmPlugin notifyOfMessage:jsonData]; + } + completionHandler(UIBackgroundFetchResultNoData); +} + @end From 2aa4c98e5ccd3de923a4a5758b364cd4405594e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Tissot?= Date: Sun, 26 Apr 2020 20:01:33 +0200 Subject: [PATCH 3/3] Added deprecation exceptions for old iOS 9 implementation. --- src/ios/AppDelegate+FCMPlugin.m | 3 +++ src/ios/FCMPluginIOS9Support.m | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/src/ios/AppDelegate+FCMPlugin.m b/src/ios/AppDelegate+FCMPlugin.m index aca7a7360..a35ce7c26 100644 --- a/src/ios/AppDelegate+FCMPlugin.m +++ b/src/ios/AppDelegate+FCMPlugin.m @@ -129,12 +129,15 @@ - (void)application:(UIApplication *)application didRegisterForRemoteNotificatio NSLog(@"Device APNS Token: %@", deviceToken); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { if (@available(iOS 10, *)) { return; } [FCMPluginIOS9Support application:application didReceiveRemoteNotification:userInfo]; } +#pragma clang diagnostic pop - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { diff --git a/src/ios/FCMPluginIOS9Support.m b/src/ios/FCMPluginIOS9Support.m index 3a6ad1af9..d13b3b555 100644 --- a/src/ios/FCMPluginIOS9Support.m +++ b/src/ios/FCMPluginIOS9Support.m @@ -11,6 +11,8 @@ @implementation FCMPluginIOS9Support NSString *const hasRequestedPushPermissionPersistenceKey = @"FCMPlugin.iOS9.hasRequestedPushPermission"; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + (void)requestPushPermission { UIUserNotificationType allNotificationTypes = (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge); @@ -22,6 +24,7 @@ + (void)requestPushPermission { [self setHasRequestedPushPermissionWithTimeout:10.0f]; }); } +#pragma clang diagnostic pop + (void)setHasRequestedPushPermissionWithTimeout:(float) timeout { [self hasPushPermission:^(NSNumber* pushPermission){ @@ -53,6 +56,8 @@ + (BOOL)getHasRequestedPushPermission { return NO; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block { NSString* apnsToken = [AppDelegate getAPNSToken]; if(apnsToken != nil) { @@ -71,6 +76,7 @@ + (void)hasPushPermission:(void (^)(NSNumber* yesNoOrNil))block { BOOL alreadyRequested = [self getHasRequestedPushPermission]; block(alreadyRequested ? [NSNumber numberWithBool:NO] : nil); } +#pragma clang diagnostic pop + (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { NSLog(@"Message ID: %@", userInfo[@"gcm.message_id"]);