diff --git a/iOS_SDK/OneSignal/OneSignal.m b/iOS_SDK/OneSignal/OneSignal.m index 801083ee5..166611e20 100755 --- a/iOS_SDK/OneSignal/OneSignal.m +++ b/iOS_SDK/OneSignal/OneSignal.m @@ -816,13 +816,22 @@ + (void)sendPurchases:(NSArray*)purchases { // - 2A. iOS 9 - Notification received while app is in focus. // - 2B. iOS 10 - Notification received/displayed while app is in focus. + (void)notificationOpened:(NSDictionary*)messageDict isActive:(BOOL)isActive { - // Should be called first, other methods relay on this global state below. - [OneSignalHelper lastMessageReceived:messageDict]; - NSDictionary* customDict = [messageDict objectForKey:@"os_data"]; if (!customDict) customDict = [messageDict objectForKey:@"custom"]; + // Prevent duplicate calls + static NSString* lastMessageID = @""; + if (customDict && customDict[@"i"]) { + NSString* currentNotificationId = customDict[@"i"]; + if ([currentNotificationId isEqualToString:lastMessageID]) + return; + lastMessageID = customDict[@"i"]; + } + + // Should be called first, other methods relay on this global state below. + [OneSignalHelper lastMessageReceived:messageDict]; + BOOL inAppAlert = false; if (isActive) { if (![[NSUserDefaults standardUserDefaults] objectForKey:@"ONESIGNAL_ALERT_OPTION"]) { @@ -869,7 +878,6 @@ + (void)notificationOpened:(NSDictionary*)messageDict isActive:(BOOL)isActive { [OneSignal submitNotificationOpened:messageId]; } else { - //app was in background / not running and opened due to a tap on a notification or an action check what type NSString* actionSelected = NULL; OSNotificationActionType type = OSNotificationActionTypeOpened; @@ -1047,8 +1055,7 @@ + (void) remoteSilentNotification:(UIApplication*)application UserInfo:(NSDictio if (userInfo[@"os_data"][@"buttons"] || userInfo[@"at"] || userInfo[@"o"]) data = userInfo; - //If buttons -> Data is buttons - //Otherwise if titles or body or attachment -> data is everything + // Genergate local notification for action button and/or attachments. if (data) { if (NSClassFromString(@"UNUserNotificationCenter")) { #if XC8_AVAILABLE @@ -1060,20 +1067,22 @@ + (void) remoteSilentNotification:(UIApplication*)application UserInfo:(NSDictio [[UIApplication sharedApplication] scheduleLocalNotification:notification]; } } - // Method was called due to a tap on a notification + // Method was called due to a tap on a notification - Fire open notification else if (application.applicationState != UIApplicationStateBackground) { [OneSignalHelper lastMessageReceived:userInfo]; - [OneSignalHelper handleNotificationReceived:OSNotificationDisplayTypeNotification]; + if (application.applicationState == UIApplicationStateActive) + [OneSignalHelper handleNotificationReceived:OSNotificationDisplayTypeNotification]; [OneSignal notificationOpened:userInfo isActive:NO]; return; } - - /* Handle the notification reception */ - [OneSignalHelper lastMessageReceived:userInfo]; - if ([OneSignalHelper isRemoteSilentNotification:userInfo]) - [OneSignalHelper handleNotificationReceived:OSNotificationDisplayTypeNone]; - else - [OneSignalHelper handleNotificationReceived:OSNotificationDisplayTypeNotification]; + // content-available notification received in the background - Fire handleNotificationReceived block in app + else { + [OneSignalHelper lastMessageReceived:userInfo]; + if ([OneSignalHelper isRemoteSilentNotification:userInfo]) + [OneSignalHelper handleNotificationReceived:OSNotificationDisplayTypeNone]; + else + [OneSignalHelper handleNotificationReceived:OSNotificationDisplayTypeNotification]; + } } // iOS 8-9 - Entry point when OneSignal action button notifiation is displayed or opened. @@ -1125,10 +1134,14 @@ + (void)syncHashedEmail:(NSString *)email { @end // Swizzles UIApplication class to swizzling the other following classes: -// - UIApplication - setDelegate: - Used to swizzle all UIApplicationDelegate selectors on the passed in class. -// - Normally this the AppDelegate class but since UIApplicationDelegate is a "interface" this could be any class. -// - UNUserNotificationCenter - setDelegate: - For iOS 10 only, swizzle all UNUserNotificationCenterDelegate selectors on the passed in class. -// - This may or may not be set so we set our own now in registerAsUNNotificationCenterDelegate to an empty class. +// - UIApplication +// - setDelegate: +// - Used to swizzle all UIApplicationDelegate selectors on the passed in class. +// - Almost always this is the AppDelegate class but since UIApplicationDelegate is an "interface" this could be any class. +// - UNUserNotificationCenter +// - setDelegate: +// - For iOS 10 only, swizzle all UNUserNotificationCenterDelegate selectors on the passed in class. +// - This may or may not be set so we set our own now in registerAsUNNotificationCenterDelegate to an empty class. // // Note1: Do NOT move this category to it's own file. This is requried so when the app developer calls OneSignal.initWithLaunchOptions this load+ // will fire along with it. This is due to how iOS loads .m files into memory instead of classes. diff --git a/iOS_SDK/OneSignal/OneSignalHelper.h b/iOS_SDK/OneSignal/OneSignalHelper.h index 3f3a30436..fa1c84dbd 100644 --- a/iOS_SDK/OneSignal/OneSignalHelper.h +++ b/iOS_SDK/OneSignal/OneSignalHelper.h @@ -57,10 +57,10 @@ #endif // - Notifications -+ (BOOL) isCapableOfGettingNotificationTypes; ++ (BOOL)isCapableOfGettingNotificationTypes; + (UILocalNotification*)prepareUILocalNotification:(NSDictionary*)data :(NSDictionary*)userInfo; + (BOOL)verifyURL:(NSString *)urlString; -+ (BOOL) isRemoteSilentNotification:(NSDictionary*)msg; ++ (BOOL)isRemoteSilentNotification:(NSDictionary*)msg; // - Networking + (NSNumber*)getNetType; diff --git a/iOS_SDK/OneSignal/OneSignalHelper.m b/iOS_SDK/OneSignal/OneSignalHelper.m index 0a9085153..4dba4a211 100644 --- a/iOS_SDK/OneSignal/OneSignalHelper.m +++ b/iOS_SDK/OneSignal/OneSignalHelper.m @@ -456,7 +456,7 @@ + (void)handleNotificationReceived:(OSNotificationDisplayType)displayType { OSNotificationPayload *payload = [[OSNotificationPayload alloc] initWithRawMessage:lastMessageReceived]; OSNotification *notification = [[OSNotification alloc] initWithPayload:payload displayType:displayType]; - //Prevent duplicate calls to same action + // Prevent duplicate calls to same receive event static NSString* lastMessageID = @""; if ([payload.notificationID isEqualToString:lastMessageID]) return; @@ -474,7 +474,7 @@ + (void)handleNotificationAction:(OSNotificationActionType)actionType actionID:( OSNotification *notification = [[OSNotification alloc] initWithPayload:payload displayType:displayType]; OSNotificationOpenedResult * result = [[OSNotificationOpenedResult alloc] initWithNotification:notification action:action]; - //Prevent duplicate calls to same action + // Prevent duplicate calls to same action static NSString* lastMessageID = @""; if ([payload.notificationID isEqualToString:lastMessageID]) return; diff --git a/iOS_SDK/OneSignal/UNUserNotificationCenter+OneSignal.m b/iOS_SDK/OneSignal/UNUserNotificationCenter+OneSignal.m index 42ea22dc8..ca7854255 100644 --- a/iOS_SDK/OneSignal/UNUserNotificationCenter+OneSignal.m +++ b/iOS_SDK/OneSignal/UNUserNotificationCenter+OneSignal.m @@ -32,6 +32,7 @@ #import "OneSignal.h" #import "OneSignalHelper.h" #import "OneSignalSelectorHelpers.h" +#import "UIApplicationDelegate+OneSignal.h" #if XC8_AVAILABLE @@ -117,6 +118,7 @@ - (void)onesignalUserNotificationCenter:(UNUserNotificationCenter *)center isTextReply:false actionIdentifier:nil userText:nil + fromPresentNotification:true withCompletionHandler:^() {}]; } @@ -147,6 +149,7 @@ - (void)onesignalUserNotificationCenter:(UNUserNotificationCenter *)center isTextReply:isTextReply actionIdentifier:response.actionIdentifier userText:userText + fromPresentNotification:false withCompletionHandler:completionHandler]; } else @@ -187,6 +190,7 @@ + (void)callLegacyAppDeletegateSelector:(UNNotification *)notification isTextReply:(BOOL)isTextReply actionIdentifier:(NSString*)actionIdentifier userText:(NSString*)userText + fromPresentNotification:(BOOL)fromPresentNotification withCompletionHandler:(void(^)())completionHandler { [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"callLegacyAppDeletegateSelector:withCompletionHandler: Fired!"]; @@ -252,8 +256,12 @@ + (void)callLegacyAppDeletegateSelector:(UNNotification *)notification [sharedApp.delegate application:sharedApp handleActionWithIdentifier:actionIdentifier forRemoteNotification:remoteUserInfo completionHandler:^() { completionHandler(); }]; - else if ([sharedApp.delegate respondsToSelector:@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)]) { - // NOTE: Should always be true as our AppDelegate swizzling should be there unless something else unswizzled it. + // Always trigger selector for open events and for non-content-available receive events. + // content-available seema to be an odd expection to iOS 10's fallback rules for legacy selectors. + else if ([sharedApp.delegate respondsToSelector:@selector(application:didReceiveRemoteNotification:fetchCompletionHandler:)] && + (!fromPresentNotification || + ![[notification.request.trigger valueForKey:@"_isContentAvailable"] boolValue])) { + // NOTE: Should always be true as our AppDelegate swizzling should be there unless something else unswizzled it. [sharedApp.delegate application:sharedApp didReceiveRemoteNotification:remoteUserInfo fetchCompletionHandler:^(UIBackgroundFetchResult result) { // Call iOS 10's compleationHandler from iOS 9's completion handler. completionHandler(); @@ -262,6 +270,8 @@ + (void)callLegacyAppDeletegateSelector:(UNNotification *)notification else completionHandler(); } + else + completionHandler(); } @end