From 467be7ac9dd9ae21d5e5006179f504ec99734f1f Mon Sep 17 00:00:00 2001 From: Brad Hesse Date: Thu, 15 Mar 2018 16:13:35 -0700 Subject: [PATCH 1/4] Extension Badge Handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Moves badge increment/decrement logic from the OneSignal backend to the application itself • This is accomplished using an app extension with an 'app group' to allow communication of data between the host app and it's notification extension service • This allows the app to maintain a consistent badge count • Also cleaned up some Firebase code and moved common strings to a definitions file • Changed the SDK so that it will default to group.{bundle_id}.onesignal as the App Group name if one is not provided in Info.plist --- .../OneSignal.xcodeproj/project.pbxproj | 10 ++++ .../Source/OSNotificationPayload.m | 1 + iOS_SDK/OneSignalSDK/Source/OneSignal.h | 1 + iOS_SDK/OneSignalSDK/Source/OneSignal.m | 12 +++-- .../Source/OneSignalCommonDefines.h | 11 +++++ .../Source/OneSignalExtensionBadgeHandler.h | 16 +++++++ .../Source/OneSignalExtensionBadgeHandler.m | 48 +++++++++++++++++++ ...ignalNotificationServiceExtensionHandler.m | 5 +- .../Source/OneSignalTrackFirebaseAnalytics.m | 23 ++++----- 9 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.h create mode 100644 iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.m diff --git a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj index 973185ae0..5b0d4e388 100644 --- a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj +++ b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj @@ -148,6 +148,9 @@ CA97E14F2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; CA97E1502051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; CA97E1512051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; + CAABF34B205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */; }; + CAABF34C205B157B0042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */; }; + CAABF34D205B157B0042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */; }; CAEA1C66202BB3C600FBFE9E /* OSEmailSubscription.h in Headers */ = {isa = PBXBuildFile; fileRef = CA810FCF202BA97300A60FED /* OSEmailSubscription.h */; }; /* End PBXBuildFile section */ @@ -283,6 +286,8 @@ CA810FD0202BA97300A60FED /* OSEmailSubscription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSEmailSubscription.m; sourceTree = ""; }; CA97E14C2051C0A5003B8CB8 /* OneSignalWebOpenDialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalWebOpenDialog.h; sourceTree = ""; }; CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalWebOpenDialog.m; sourceTree = ""; }; + CAABF349205B15780042F8E5 /* OneSignalExtensionBadgeHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalExtensionBadgeHandler.h; sourceTree = ""; }; + CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalExtensionBadgeHandler.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -452,6 +457,8 @@ 4529DF0B1FA932AC00CEAB1D /* OneSignalTrackFirebaseAnalytics.m */, 454F94F01FAD218000D74CCF /* OneSignalNotificationServiceExtensionHandler.h */, 454F94F11FAD218000D74CCF /* OneSignalNotificationServiceExtensionHandler.m */, + CAABF349205B15780042F8E5 /* OneSignalExtensionBadgeHandler.h */, + CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */, ); path = Source; sourceTree = ""; @@ -731,6 +738,7 @@ 454F94F51FAD2E5A00D74CCF /* OSNotificationPayload.m in Sources */, 9129C6BE1E89E7AB009CB6A0 /* OSSubscription.m in Sources */, 912412361E73342200E41FD7 /* OneSignalTrackIAP.m in Sources */, + CAABF34B205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */, CA08FC7F1FE99B25004C445F /* Requests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -768,6 +776,7 @@ 1AF75EB01E8569720097B315 /* NSString+OneSignal.m in Sources */, 9129C6BF1E89E7AB009CB6A0 /* OSSubscription.m in Sources */, 912412371E73342200E41FD7 /* OneSignalTrackIAP.m in Sources */, + CAABF34C205B157B0042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */, CA08FC801FE99B25004C445F /* Requests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -785,6 +794,7 @@ CA70E3372023D51300019273 /* OneSignalSetEmailParameters.m in Sources */, 4529DED81FA8253D00CEAB1D /* NSUserDefaultsOverrider.m in Sources */, 4529DEED1FA83C5D00CEAB1D /* OneSignalHelperOverrider.m in Sources */, + CAABF34D205B157B0042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */, 912412301E73342200E41FD7 /* OneSignalSelectorHelpers.m in Sources */, 91F58D851E7C88230017D24D /* OneSignalNotificationSettingsIOS10.m in Sources */, 912412241E73342200E41FD7 /* OneSignalLocation.m in Sources */, diff --git a/iOS_SDK/OneSignalSDK/Source/OSNotificationPayload.m b/iOS_SDK/OneSignalSDK/Source/OSNotificationPayload.m index ed140eaaa..1b81db7d5 100644 --- a/iOS_SDK/OneSignalSDK/Source/OSNotificationPayload.m +++ b/iOS_SDK/OneSignalSDK/Source/OSNotificationPayload.m @@ -118,6 +118,7 @@ -(void)parseCommonOneSignalFields:(NSDictionary*)payload { _launchURL = payload[@"u"]; _templateID = payload[@"ti"]; _templateName = payload[@"tn"]; + _badgeIncrement = [_rawPayload[@"badge_inc"] integerValue]; } -(void)parseApnsFields { diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.h b/iOS_SDK/OneSignalSDK/Source/OneSignal.h index 0194f8469..4ce7aac90 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.h @@ -122,6 +122,7 @@ typedef NS_ENUM(NSUInteger, OSNotificationDisplayType) { /* The badge assigned to the application icon */ @property(readonly)NSUInteger badge; +@property(readonly)NSInteger badgeIncrement; /* The sound parameter passed to the notification By default set to UILocalNotificationDefaultSoundName */ diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index c1e282608..89e0dfc00 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -50,6 +50,8 @@ #import "OSObservable.h" +#import "OneSignalExtensionBadgeHandler.h" + #import #import #import @@ -908,14 +910,14 @@ + (void)postNotification:(NSDictionary*)jsonData onSuccess:(OSResultSuccessBlock onesignal_Log(ONE_S_LL_DEBUG, [NSString stringWithFormat: @"HTTP create notification success %@", jsonResultsString]); if (successBlock) - successBlock(result); + successBlock(result); }); } onFailure:^(NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ onesignal_Log(ONE_S_LL_ERROR, @"Create notification failed"); onesignal_Log(ONE_S_LL_INFO, [NSString stringWithFormat: @"%@", error]); if (failureBlock) - failureBlock(error); + failureBlock(error); }); }]; } @@ -1536,7 +1538,7 @@ + (void)submitNotificationOpened:(NSString*)messageId { + (BOOL) clearBadgeCount:(BOOL)fromNotifOpened { - NSNumber *disableBadgeNumber = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"OneSignal_disable_badge_clearing"]; + NSNumber *disableBadgeNumber = [[NSBundle mainBundle] objectForInfoDictionaryKey:ONESIGNAL_DISABLE_BADGE_CLEARING]; if (disableBadgeNumber) disableBadgeClearing = [disableBadgeNumber boolValue]; @@ -1555,6 +1557,10 @@ + (BOOL) clearBadgeCount:(BOOL)fromNotifOpened { // iOS 8+ auto dismisses the notification you tap on so only clear the badge (and notifications [side-effect]) if it was set. [[UIApplication sharedApplication] setApplicationIconBadgeNumber:1]; [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; + + let defaults = [[NSUserDefaults alloc] initWithSuiteName:[OneSignalExtensionBadgeHandler appGroupName]]; + [defaults setObject:@0 forKey:ONESIGNAL_BADGE_KEY]; + [defaults synchronize]; } return wasBadgeSet; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h b/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h index 557c8979c..cbe4054b8 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h @@ -28,4 +28,15 @@ #define PROMPT_BEFORE_OPENING_PUSH_URL @"PROMPT_BEFORE_OPENING_PUSH_URL" #define DEPRECATED_SELECTORS @[@"application:didReceiveLocalNotification:", @"application:handleActionWithIdentifier:forLocalNotification:completionHandler:", @"application:handleActionWithIdentifier:forLocalNotification:withResponseInfo:completionHandler:"] +// Badge handling +#define ONESIGNAL_DISABLE_BADGE_CLEARING @"OneSignal_disable_badge_clearing" +#define ONESIGNAL_APP_GROUP_NAME_KEY @"OneSignal_app_groups_key" +#define ONESIGNAL_BADGE_KEY @"onesignalBadgeCount" + +// Firebase +#define ONESIGNAL_FB_ENABLE_FIREBASE @"OS_ENABLE_FIREBASE_ANALYTICS" +#define ONESIGNAL_FB_LAST_TIME_RECEIVED @"OS_LAST_RECIEVED_TIME" +#define ONESIGNAL_FB_LAST_GAF_CAMPAIGN_RECEIVED @"OS_LAST_RECIEVED_GAF_CAMPAIGN" +#define ONESIGNAL_FB_LAST_NOTIFICATION_ID_RECEIVED @"OS_LAST_RECIEVED_NOTIFICATION_ID" + #endif /* OneSignalCommonDefines_h */ diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.h b/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.h new file mode 100644 index 000000000..d82a9fa9b --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.h @@ -0,0 +1,16 @@ +// +// OneSignalExtensionBadgeHandler.h +// OneSignal +// +// Created by Brad Hesse on 3/15/18. +// Copyright © 2018 Hiptic. All rights reserved. +// + +#import +#import +#import "OneSignal.h" + +@interface OneSignalExtensionBadgeHandler : NSObject ++ (void)handleBadgeCountWithNotificationRequest:(UNNotificationRequest *)request withNotificationPayload:(OSNotificationPayload *)payload withMutableNotificationContent:(UNMutableNotificationContent *)replacementContent; ++ (NSString *)appGroupName; +@end diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.m b/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.m new file mode 100644 index 000000000..81ba69373 --- /dev/null +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.m @@ -0,0 +1,48 @@ +// +// OneSignalExtensionBadgeHandler.m +// OneSignal +// +// Created by Brad Hesse on 3/15/18. +// Copyright © 2018 Hiptic. All rights reserved. +// + +#import "OneSignalExtensionBadgeHandler.h" +#import "OneSignalCommonDefines.h" +#import "OneSignalHelper.h" +#import "OneSignalTrackFirebaseAnalytics.h" +#import "OSNotificationPayload+Internal.h" + +@implementation OneSignalExtensionBadgeHandler + ++ (void)handleBadgeCountWithNotificationRequest:(UNNotificationRequest *)request withNotificationPayload:(OSNotificationPayload *)payload withMutableNotificationContent:(UNMutableNotificationContent *)replacementContent { + + if (!payload.badgeIncrement) + return; + + let appGroupName = [OneSignalExtensionBadgeHandler appGroupName]; + + let userDefaults = [[NSUserDefaults alloc] initWithSuiteName:appGroupName]; + + var currentValue = [((NSNumber *)[userDefaults objectForKey:ONESIGNAL_BADGE_KEY] ?: @0) intValue]; + + currentValue += (int)payload.badgeIncrement; + + if (currentValue < 0) + currentValue = 0; + + replacementContent.badge = @(currentValue); + + [userDefaults setObject:@(currentValue) forKey:ONESIGNAL_BADGE_KEY]; + [userDefaults synchronize]; +} + ++ (NSString *)appGroupName { + var appGroupName = (NSString *)[[NSBundle mainBundle] objectForInfoDictionaryKey:ONESIGNAL_APP_GROUP_NAME_KEY]; + + if (!appGroupName) + appGroupName = [NSString stringWithFormat:@"group.%@.%@", [[NSBundle mainBundle] bundleIdentifier], @"onesignal"]; + + return [appGroupName stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; +} + +@end diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalNotificationServiceExtensionHandler.m b/iOS_SDK/OneSignalSDK/Source/OneSignalNotificationServiceExtensionHandler.m index 291c39d15..44fb7c571 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalNotificationServiceExtensionHandler.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalNotificationServiceExtensionHandler.m @@ -26,7 +26,7 @@ */ #import "OneSignalNotificationServiceExtensionHandler.h" - +#import "OneSignalExtensionBadgeHandler.h" #import "OneSignalHelper.h" #import "OneSignalTrackFirebaseAnalytics.h" #import "OSNotificationPayload+Internal.h" @@ -40,6 +40,9 @@ +(UNMutableNotificationContent*)didReceiveNotificationExtensionRequest:(UNNotifi let payload = [OSNotificationPayload parseWithApns:request.content.userInfo]; + //handle badge count + [OneSignalExtensionBadgeHandler handleBadgeCountWithNotificationRequest:request withNotificationPayload:payload withMutableNotificationContent:replacementContent]; + // Track receieved [OneSignalTrackFirebaseAnalytics trackReceivedEvent:payload]; diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalTrackFirebaseAnalytics.m b/iOS_SDK/OneSignalSDK/Source/OneSignalTrackFirebaseAnalytics.m index 183104550..0997b831c 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalTrackFirebaseAnalytics.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalTrackFirebaseAnalytics.m @@ -27,6 +27,8 @@ #import "OneSignalTrackFirebaseAnalytics.h" #import "OneSignalHelper.h" +#import "OneSignalCommonDefines.h" +#import "OneSignalExtensionBadgeHandler.h" @implementation OneSignalTrackFirebaseAnalytics @@ -43,7 +45,7 @@ +(BOOL)needsRemoteParams { // extension target to track inflenced opens. +(void)init { let userDefaults = [[NSUserDefaults alloc] initWithSuiteName:[self appGroupKey]]; - trackingEnabled = [userDefaults boolForKey:@"OS_ENABLE_FIREBASE_ANALYTICS"]; + trackingEnabled = [userDefaults boolForKey:ONESIGNAL_FB_ENABLE_FIREBASE]; } @@ -51,14 +53,13 @@ +(void)updateFromDownloadParams:(NSDictionary*)params { trackingEnabled = (BOOL)params[@"fba"]; let userDefaults = [[NSUserDefaults alloc] initWithSuiteName:[self appGroupKey]]; if (trackingEnabled) - [userDefaults setBool:true forKey:@"OS_ENABLE_FIREBASE_ANALYTICS"]; + [userDefaults setBool:true forKey:ONESIGNAL_FB_ENABLE_FIREBASE]; else - [userDefaults removeObjectForKey:@"OS_ENABLE_FIREBASE_ANALYTICS"]; + [userDefaults removeObjectForKey:ONESIGNAL_FB_ENABLE_FIREBASE]; } +(NSString*)appGroupKey { - NSString *groupKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"OneSignal_app_groups_key"]; - return [groupKey stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + return [OneSignalExtensionBadgeHandler appGroupName]; } +(void)logEventWithName:(NSString*)name parameters:(NSDictionary*)params { @@ -105,9 +106,9 @@ +(void)trackReceivedEvent:(OSNotificationPayload*)payload { let campaign = [self getCampaignNameFromPayload:payload]; let userDefaults = [[NSUserDefaults alloc] initWithSuiteName:[self appGroupKey]]; - [userDefaults setObject:payload.notificationID forKey:@"OS_LAST_RECIEVED_NOTIFICATION_ID"]; - [userDefaults setObject:campaign forKey:@"OS_LAST_RECIEVED_GAF_CAMPAIGN"]; - [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:@"OS_LAST_RECIEVED_TIME"]; + [userDefaults setObject:payload.notificationID forKey:ONESIGNAL_FB_LAST_NOTIFICATION_ID_RECEIVED]; + [userDefaults setObject:campaign forKey:ONESIGNAL_FB_LAST_GAF_CAMPAIGN_RECEIVED]; + [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:ONESIGNAL_FB_LAST_TIME_RECEIVED]; [userDefaults synchronize]; [self logEventWithName:@"os_notification_received" @@ -124,7 +125,7 @@ +(void)trackInfluenceOpenEvent { return; let userDefaults = [[NSUserDefaults alloc] initWithSuiteName:[self appGroupKey]]; - NSTimeInterval lastTimeReceived = [userDefaults doubleForKey:@"OS_LAST_RECIEVED_TIME"]; + NSTimeInterval lastTimeReceived = [userDefaults doubleForKey:ONESIGNAL_FB_LAST_TIME_RECEIVED]; if (lastTimeReceived == 0) return; @@ -140,8 +141,8 @@ +(void)trackInfluenceOpenEvent { if (now - lastOpenedTime < 30) return; - NSString *notificationId = [userDefaults objectForKey:@"OS_LAST_RECIEVED_NOTIFICATION_ID"]; - NSString *campaign = [userDefaults objectForKey:@"OS_LAST_RECIEVED_GAF_CAMPAIGN"]; + NSString *notificationId = [userDefaults objectForKey:ONESIGNAL_FB_LAST_NOTIFICATION_ID_RECEIVED]; + NSString *campaign = [userDefaults objectForKey:ONESIGNAL_FB_LAST_GAF_CAMPAIGN_RECEIVED]; [self logEventWithName:@"os_notification_influence_open" parameters:@{ From d961f6e9886d2f561ee94df0ea4304630b0b5a59 Mon Sep 17 00:00:00 2001 From: Brad Hesse Date: Thu, 22 Mar 2018 12:47:47 -0700 Subject: [PATCH 2/4] Swizzle setApplicationIconBadgeNumber() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Swizzles the setApplicationIconBadgeNumber() method so the SDK always has a consistent badge count even if the developer manually sets it. --- iOS_SDK/OneSignalSDK/Source/OneSignal.m | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index 89e0dfc00..b14d015a9 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -394,6 +394,8 @@ + (id)initWithLaunchOptions:(NSDictionary*)launchOptions appId:(NSString*)appId withUserDefaults:userDefaults withSettings:settings]; + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:23]; + if (!success) return self; @@ -1557,10 +1559,6 @@ + (BOOL) clearBadgeCount:(BOOL)fromNotifOpened { // iOS 8+ auto dismisses the notification you tap on so only clear the badge (and notifications [side-effect]) if it was set. [[UIApplication sharedApplication] setApplicationIconBadgeNumber:1]; [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; - - let defaults = [[NSUserDefaults alloc] initWithSuiteName:[OneSignalExtensionBadgeHandler appGroupName]]; - [defaults setObject:@0 forKey:ONESIGNAL_BADGE_KEY]; - [defaults synchronize]; } return wasBadgeSet; @@ -1949,9 +1947,23 @@ + (void)load { // Swizzle - UIApplication delegate injectToProperClass(@selector(setOneSignalDelegate:), @selector(setDelegate:), @[], [OneSignalAppDelegate class], [UIApplication class]); + injectToProperClass(@selector(onesignalSetApplicationIconBadgeNumber:), @selector(setApplicationIconBadgeNumber:), @[], [OneSignalAppDelegate class], [UIApplication class]); + [self setupUNUserNotificationCenterDelegate]; } +/* + In order for the badge count to be consistent even in situations where the developer manually sets the badge number, + We swizzle the 'setApplicationIconBadgeNumber()' to intercept these calls so we always know the latest count +*/ +- (void)onesignalSetApplicationIconBadgeNumber:(NSInteger)badge { + let defaults = [[NSUserDefaults alloc] initWithSuiteName:[OneSignalExtensionBadgeHandler appGroupName]]; + [defaults setObject:@(badge) forKey:ONESIGNAL_BADGE_KEY]; + [defaults synchronize]; + + [self onesignalSetApplicationIconBadgeNumber:badge]; +} + +(void)setupUNUserNotificationCenterDelegate { // Swizzle - UNUserNotificationCenter delegate - iOS 10+ if (!NSClassFromString(@"UNUserNotificationCenter")) From 56bbcb540942dd5421a3b5483172b045cec6847c Mon Sep 17 00:00:00 2001 From: Brad Hesse Date: Thu, 22 Mar 2018 14:19:34 -0700 Subject: [PATCH 3/4] Add Tests for Badge Handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Adds a test to verify the extension badge handling logic works correctly • Verifies that manually setting the badge number using UIApplication setApplicationIconBadgeNumber() also updates OneSignal SDK's cached badge value • Verifies that the SDK correctly handles positive and negative (increment and decrement) badge_inc values --- iOS_SDK/OneSignalSDK/Source/OneSignal.m | 2 - .../UnitTests/UnitTestCommonMethods.h | 3 + .../UnitTests/UnitTestCommonMethods.m | 28 ++++++ iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m | 93 +++++++++++-------- 4 files changed, 86 insertions(+), 40 deletions(-) diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index b14d015a9..5e692a2e5 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -394,8 +394,6 @@ + (id)initWithLaunchOptions:(NSDictionary*)launchOptions appId:(NSString*)appId withUserDefaults:userDefaults withSettings:settings]; - [[UIApplication sharedApplication] setApplicationIconBadgeNumber:23]; - if (!success) return self; diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h b/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h index 318357452..ef8bc1d26 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h @@ -10,6 +10,8 @@ #import #import "OneSignal.h" +NSString * serverUrlWithPath(NSString *path); + @interface UnitTestCommonMethods : NSObject + (void)setCurrentNotificationPermissionAsUnanswered; @@ -18,6 +20,7 @@ + (void)runBackgroundThreads; + (void)beforeAllTest; + (void)clearStateForAppRestart:(XCTestCase *)testCase; ++ (UNNotificationResponse*)createBasiciOSNotificationResponseWithPayload:(NSDictionary*)userInfo; @end diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m b/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m index 37f15e6cb..19a56c55e 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m @@ -22,6 +22,12 @@ #import "OneSignalTrackFirebaseAnalyticsOverrider.h" #import "UIAlertViewOverrider.h" #import "NSObjectOverrider.h" +#import "OneSignalCommonDefines.h" + + +NSString * serverUrlWithPath(NSString *path) { + return [NSString stringWithFormat:@"%@%@%@", SERVER_URL, API_VERSION, path]; +} @interface OneSignal (UN_extra) + (dispatch_queue_t) getRegisterQueue; @@ -61,6 +67,28 @@ + (void)runBackgroundThreads { NSLog(@"END runBackgroundThreads"); } ++ (UNNotificationResponse*)createBasiciOSNotificationResponseWithPayload:(NSDictionary*)userInfo { + // Mocking an iOS 10 notification + // Setting response.notification.request.content.userInfo + UNNotificationResponse *notifResponse = [UNNotificationResponse alloc]; + + // Normal tap on notification + [notifResponse setValue:@"com.apple.UNNotificationDefaultActionIdentifier" forKeyPath:@"actionIdentifier"]; + + UNNotificationContent *unNotifContent = [UNNotificationContent alloc]; + UNNotification *unNotif = [UNNotification alloc]; + UNNotificationRequest *unNotifRequqest = [UNNotificationRequest alloc]; + // Set as remote push type + [unNotifRequqest setValue:[UNPushNotificationTrigger alloc] forKey:@"trigger"]; + + [unNotif setValue:unNotifRequqest forKeyPath:@"request"]; + [notifResponse setValue:unNotif forKeyPath:@"notification"]; + [unNotifRequqest setValue:unNotifContent forKeyPath:@"content"]; + [unNotifContent setValue:userInfo forKey:@"userInfo"]; + + return notifResponse; +} + + (void)clearStateForAppRestart:(XCTestCase *)testCase { NSLog(@"======= APP RESTART ======\n\n"); diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m index bc6e97544..3c1e25d28 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m @@ -58,6 +58,8 @@ #import "UnitTestAppDelegate.h" +#import "OneSignalExtensionBadgeHandler.h" + // Shadows #import "NSObjectOverrider.h" #import "NSUserDefaultsOverrider.h" @@ -78,10 +80,6 @@ #import "OneSignalCommonDefines.h" -NSString * serverUrlWithPath(NSString *path) { - return [NSString stringWithFormat:@"%@%@%@", SERVER_URL, API_VERSION, path]; -} - @interface UnitTests : XCTestCase @end @@ -175,35 +173,13 @@ - (void)backgroundApp { UIApplication *sharedApp = [UIApplication sharedApplication]; [sharedApp.delegate applicationWillResignActive:sharedApp]; } - -- (UNNotificationResponse*)createBasiciOSNotificationResponseWithPayload:(NSDictionary*)userInfo { - // Mocking an iOS 10 notification - // Setting response.notification.request.content.userInfo - UNNotificationResponse *notifResponse = [UNNotificationResponse alloc]; - - // Normal tap on notification - [notifResponse setValue:@"com.apple.UNNotificationDefaultActionIdentifier" forKeyPath:@"actionIdentifier"]; - - UNNotificationContent *unNotifContent = [UNNotificationContent alloc]; - UNNotification *unNotif = [UNNotification alloc]; - UNNotificationRequest *unNotifRequqest = [UNNotificationRequest alloc]; - // Set as remote push type - [unNotifRequqest setValue:[UNPushNotificationTrigger alloc] forKey:@"trigger"]; - - [unNotif setValue:unNotifRequqest forKeyPath:@"request"]; - [notifResponse setValue:unNotif forKeyPath:@"notification"]; - [unNotifRequqest setValue:unNotifContent forKeyPath:@"content"]; - [unNotifContent setValue:userInfo forKey:@"userInfo"]; - - return notifResponse; -} - (UNNotificationResponse*)createBasiciOSNotificationResponse { id userInfo = @{@"custom": @{@"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"} }; - return [self createBasiciOSNotificationResponseWithPayload:userInfo]; + return [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; } @@ -949,7 +925,7 @@ - (UNNotificationResponse*)createNotificationResponseForAnalyticsTests { } }; - return [self createBasiciOSNotificationResponseWithPayload:userInfo]; + return [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; } - (void)testFirebaseAnalyticsNotificationOpen { @@ -1072,7 +1048,7 @@ - (void)testNotificationOpenFromButtonPress { } }; - id notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; [notifResponse setValue:@"id1" forKeyPath:@"actionIdentifier"]; UNUserNotificationCenter *notifCenter = [UNUserNotificationCenter currentNotificationCenter]; @@ -1120,7 +1096,7 @@ - (void)testNotificationOpenFromButtonPressWithNewformat { @"buttons": @[@{@"i": @"id1", @"n": @"text1"}], }}; - id notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; [notifResponse setValue:@"id1" forKeyPath:@"actionIdentifier"]; UNUserNotificationCenter *notifCenter = [UNUserNotificationCenter currentNotificationCenter]; @@ -1163,7 +1139,7 @@ - (void)notificationAlertButtonsDisplayWithFormat:(NSDictionary *)userInfo { [UnitTestCommonMethods resumeApp]; [UnitTestCommonMethods runBackgroundThreads]; - id notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; [notifResponse setValue:@"id1" forKeyPath:@"actionIdentifier"]; UNUserNotificationCenter *notifCenter = [UNUserNotificationCenter currentNotificationCenter]; @@ -1224,7 +1200,7 @@ - (void)testOpeningWithAdditionalData { @"a": @{ @"foo": @"bar" } }}; - id notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; UNUserNotificationCenter *notifCenter = [UNUserNotificationCenter currentNotificationCenter]; id notifCenterDelegate = notifCenter.delegate; @@ -1243,7 +1219,7 @@ - (void)testOpeningWithAdditionalData { @"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55bc" }, @"foo": @"bar"}; - notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; [notifCenterDelegate userNotificationCenter:notifCenter didReceiveNotificationResponse:notifResponse withCompletionHandler:^() {}]; XCTAssertEqual(openedWasFire, true); */ @@ -1264,7 +1240,7 @@ - (void)receivedCallbackWithButtonsWithUserInfo:(NSDictionary *)userInfo { settings:nil]; [UnitTestCommonMethods runBackgroundThreads]; - let notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + let notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; UNUserNotificationCenter *notifCenter = [UNUserNotificationCenter currentNotificationCenter]; let notifCenterDelegate = notifCenter.delegate; @@ -1639,7 +1615,7 @@ -(UNNotificationCategory*)unNotificagionCategoryWithId:(NSString*)identifier { // iOS 10 - Notification Service Extension test - (void) didReceiveNotificationExtensionRequestDontOverrideCateogoryWithUserInfo:(NSDictionary *)userInfo { - id notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; [[notifResponse notification].request.content setValue:@"some_category" forKey:@"categoryIdentifier"]; @@ -1695,7 +1671,7 @@ - (void) testDidReceiveNotificationExtensionRequestDontOverrideCateogory { @"att": @{ @"id": @"http://domain.com/file.jpg" } }}; - id notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; [[notifResponse notification].request.content setValue:@"some_category" forKey:@"categoryIdentifier"]; @@ -1719,7 +1695,7 @@ - (void) testDidReceiveNotificationExtensionRequestLocalFile { @"att": @{ @"id": @"file.jpg" } }}; - id notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; UNMutableNotificationContent* content = [OneSignal didReceiveNotificationExtensionRequest:[notifResponse notification].request withMutableNotificationContent:nil]; @@ -1740,7 +1716,7 @@ - (void) testServiceExtensionTimeWillExpireRequest { @"att": @{ @"id": @"http://domain.com/file.jpg" } }}; - id notifResponse = [self createBasiciOSNotificationResponseWithPayload:userInfo]; + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; UNMutableNotificationContent* content = [OneSignal serviceExtensionTimeWillExpireRequest:[notifResponse notification].request withMutableNotificationContent:nil]; @@ -1835,4 +1811,45 @@ -(void)testDelayedSubscriptionUpdate { XCTAssertTrue(observer->last.to.subscribed); } +- (void)testBadgeExtensionUpdate { + + let defaults = [[NSUserDefaults alloc] initWithSuiteName:[OneSignalExtensionBadgeHandler appGroupName]]; + [defaults setObject:@2 forKey:ONESIGNAL_BADGE_KEY]; + [defaults synchronize]; + + //test that manually setting the badge number also updates NSUserDefaults for our app group + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; + + XCTAssert([(NSNumber *)[defaults objectForKey:ONESIGNAL_BADGE_KEY] isEqualToNumber:@0]); + + NSMutableDictionary * userInfo = [@{ + @"aps": @{ + @"mutable-content": @1, + @"alert": @"Message Body" + }, + @"os_data": @{ + @"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba", + @"buttons": @[@{@"i": @"id1", @"n": @"text1"}], + @"att": @{ @"id": @"http://domain.com/file.jpg" } + }, + @"badge_inc" : @3 + } mutableCopy]; + + id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; + + //test that receiving a notification with badge_inc updates the badge icon number + [OneSignal didReceiveNotificationExtensionRequest:[notifResponse notification].request withMutableNotificationContent:nil]; + + XCTAssert([(NSNumber *)[defaults objectForKey:ONESIGNAL_BADGE_KEY] isEqualToNumber:@3]); + + //test that a negative badge_inc value decrements correctly + [userInfo setObject:@-1 forKey:@"badge_inc"]; + + id newNotifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; + + [OneSignal didReceiveNotificationExtensionRequest:[newNotifResponse notification].request withMutableNotificationContent:nil]; + + XCTAssert([(NSNumber *)[defaults objectForKey:ONESIGNAL_BADGE_KEY] isEqualToNumber:@2]); +} + @end From 94c1843749f157a71f1e9e035f319e9849b60db2 Mon Sep 17 00:00:00 2001 From: Brad Hesse Date: Thu, 22 Mar 2018 16:06:39 -0700 Subject: [PATCH 4/4] Improve Badge Tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Modularizes access to NSUserDefaults in regards to badge logic to a single implementation file • Moves the badge_inc property into the 'os_data' or 'custom' fields in push notification objects • Extends badge tests to cover more scenarios • Fixes header copyrights in multiple files --- .../OneSignal.xcodeproj/project.pbxproj | 4 + .../Source/OSNotificationPayload.m | 2 +- iOS_SDK/OneSignalSDK/Source/OneSignal.m | 4 +- .../Source/OneSignalCommonDefines.h | 33 +++- .../Source/OneSignalExtensionBadgeHandler.h | 35 +++- .../Source/OneSignalExtensionBadgeHandler.m | 65 +++++-- .../Source/OneSignalSetEmailParameters.h | 33 +++- .../Source/OneSignalSetEmailParameters.m | 33 +++- .../OneSignalSDK/Source/ReattemptRequest.h | 33 +++- .../OneSignalSDK/Source/ReattemptRequest.m | 33 +++- iOS_SDK/OneSignalSDK/UnitTests/BadgeTests.m | 159 ++++++++++++++++++ iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m | 33 +++- .../Shadows/OneSignalClientOverrider.h | 33 +++- .../Shadows/OneSignalClientOverrider.m | 41 +++-- .../UnitTests/UnitTestCommonMethods.h | 33 +++- .../UnitTests/UnitTestCommonMethods.m | 33 +++- iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m | 41 ----- 17 files changed, 504 insertions(+), 144 deletions(-) create mode 100644 iOS_SDK/OneSignalSDK/UnitTests/BadgeTests.m diff --git a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj index 5b0d4e388..656b2526f 100644 --- a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj +++ b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj @@ -148,6 +148,7 @@ CA97E14F2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; CA97E1502051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; CA97E1512051C0A5003B8CB8 /* OneSignalWebOpenDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */; }; + CAA4ED0120646762005BD59B /* BadgeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CAA4ED0020646762005BD59B /* BadgeTests.m */; }; CAABF34B205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */; }; CAABF34C205B157B0042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */; }; CAABF34D205B157B0042F8E5 /* OneSignalExtensionBadgeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */; }; @@ -286,6 +287,7 @@ CA810FD0202BA97300A60FED /* OSEmailSubscription.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OSEmailSubscription.m; sourceTree = ""; }; CA97E14C2051C0A5003B8CB8 /* OneSignalWebOpenDialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalWebOpenDialog.h; sourceTree = ""; }; CA97E14D2051C0A5003B8CB8 /* OneSignalWebOpenDialog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalWebOpenDialog.m; sourceTree = ""; }; + CAA4ED0020646762005BD59B /* BadgeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BadgeTests.m; sourceTree = ""; }; CAABF349205B15780042F8E5 /* OneSignalExtensionBadgeHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalExtensionBadgeHandler.h; sourceTree = ""; }; CAABF34A205B15780042F8E5 /* OneSignalExtensionBadgeHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalExtensionBadgeHandler.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -411,6 +413,7 @@ children = ( 4529DECD1FA81DE000CEAB1D /* Shadows */, 911E2CBC1E398AB3003112A4 /* UnitTests.m */, + CAA4ED0020646762005BD59B /* BadgeTests.m */, CA63AF8320211F7400E340FB /* EmailTests.m */, CA63AF8520211FF800E340FB /* UnitTestCommonMethods.h */, CA63AF8620211FF800E340FB /* UnitTestCommonMethods.m */, @@ -798,6 +801,7 @@ 912412301E73342200E41FD7 /* OneSignalSelectorHelpers.m in Sources */, 91F58D851E7C88230017D24D /* OneSignalNotificationSettingsIOS10.m in Sources */, 912412241E73342200E41FD7 /* OneSignalLocation.m in Sources */, + CAA4ED0120646762005BD59B /* BadgeTests.m in Sources */, 912412491E73369800E41FD7 /* OneSignalHelper.m in Sources */, 4529DEE41FA82C6200CEAB1D /* NSURLSessionOverrider.m in Sources */, 4529DED21FA81EA800CEAB1D /* NSObjectOverrider.m in Sources */, diff --git a/iOS_SDK/OneSignalSDK/Source/OSNotificationPayload.m b/iOS_SDK/OneSignalSDK/Source/OSNotificationPayload.m index 1b81db7d5..98d96c740 100644 --- a/iOS_SDK/OneSignalSDK/Source/OSNotificationPayload.m +++ b/iOS_SDK/OneSignalSDK/Source/OSNotificationPayload.m @@ -118,7 +118,7 @@ -(void)parseCommonOneSignalFields:(NSDictionary*)payload { _launchURL = payload[@"u"]; _templateID = payload[@"ti"]; _templateName = payload[@"tn"]; - _badgeIncrement = [_rawPayload[@"badge_inc"] integerValue]; + _badgeIncrement = [payload[@"badge_inc"] integerValue]; } -(void)parseApnsFields { diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index 5e692a2e5..e3244de34 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -1955,9 +1955,7 @@ + (void)load { We swizzle the 'setApplicationIconBadgeNumber()' to intercept these calls so we always know the latest count */ - (void)onesignalSetApplicationIconBadgeNumber:(NSInteger)badge { - let defaults = [[NSUserDefaults alloc] initWithSuiteName:[OneSignalExtensionBadgeHandler appGroupName]]; - [defaults setObject:@(badge) forKey:ONESIGNAL_BADGE_KEY]; - [defaults synchronize]; + [OneSignalExtensionBadgeHandler updateCachedBadgeValue:badge]; [self onesignalSetApplicationIconBadgeNumber:badge]; } diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h b/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h index cbe4054b8..bbc73c3cd 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalCommonDefines.h @@ -1,10 +1,29 @@ -// -// OneSignalCommonDefines.h -// OneSignal -// -// Created by Brad Hesse on 2/1/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #ifndef OneSignalCommonDefines_h #define OneSignalCommonDefines_h diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.h b/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.h index d82a9fa9b..cb61d7dec 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.h @@ -1,10 +1,29 @@ -// -// OneSignalExtensionBadgeHandler.h -// OneSignal -// -// Created by Brad Hesse on 3/15/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import #import @@ -12,5 +31,7 @@ @interface OneSignalExtensionBadgeHandler : NSObject + (void)handleBadgeCountWithNotificationRequest:(UNNotificationRequest *)request withNotificationPayload:(OSNotificationPayload *)payload withMutableNotificationContent:(UNMutableNotificationContent *)replacementContent; ++ (void)updateCachedBadgeValue:(NSInteger)value; ++ (NSInteger)currentCachedBadgeValue; + (NSString *)appGroupName; @end diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.m b/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.m index 81ba69373..6a4ac8fdb 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalExtensionBadgeHandler.m @@ -1,10 +1,29 @@ -// -// OneSignalExtensionBadgeHandler.m -// OneSignal -// -// Created by Brad Hesse on 3/15/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import "OneSignalExtensionBadgeHandler.h" #import "OneSignalCommonDefines.h" @@ -16,23 +35,41 @@ @implementation OneSignalExtensionBadgeHandler + (void)handleBadgeCountWithNotificationRequest:(UNNotificationRequest *)request withNotificationPayload:(OSNotificationPayload *)payload withMutableNotificationContent:(UNMutableNotificationContent *)replacementContent { - if (!payload.badgeIncrement) + //if the user is setting the badge directly instead of incrementing/decrementing, + //make sure the OneSignal cached value is updated to this value + if (!payload.badgeIncrement) { + if (payload.badge) + [OneSignalExtensionBadgeHandler updateCachedBadgeValue:payload.badge]; + return; + } - let appGroupName = [OneSignalExtensionBadgeHandler appGroupName]; - - let userDefaults = [[NSUserDefaults alloc] initWithSuiteName:appGroupName]; - - var currentValue = [((NSNumber *)[userDefaults objectForKey:ONESIGNAL_BADGE_KEY] ?: @0) intValue]; + var currentValue = (int)OneSignalExtensionBadgeHandler.currentCachedBadgeValue ?: 0; currentValue += (int)payload.badgeIncrement; + //cannot have negative badge values if (currentValue < 0) currentValue = 0; replacementContent.badge = @(currentValue); - [userDefaults setObject:@(currentValue) forKey:ONESIGNAL_BADGE_KEY]; + [OneSignalExtensionBadgeHandler updateCachedBadgeValue:currentValue]; +} + ++ (NSInteger)currentCachedBadgeValue { + let userDefaults = [[NSUserDefaults alloc] initWithSuiteName:OneSignalExtensionBadgeHandler.appGroupName]; + + return [(NSNumber *)[userDefaults objectForKey:ONESIGNAL_BADGE_KEY] integerValue]; +} + ++ (void)updateCachedBadgeValue:(NSInteger)value { + //since badge logic can be executed in an extension, we need to use app groups to get + //a shared NSUserDefaults from the app group suite name + let userDefaults = [[NSUserDefaults alloc] initWithSuiteName:OneSignalExtensionBadgeHandler.appGroupName]; + + [userDefaults setObject:@(value) forKey:ONESIGNAL_BADGE_KEY]; + [userDefaults synchronize]; } diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalSetEmailParameters.h b/iOS_SDK/OneSignalSDK/Source/OneSignalSetEmailParameters.h index 846ce466a..2682a79cd 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalSetEmailParameters.h +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalSetEmailParameters.h @@ -1,10 +1,29 @@ -// -// OneSignalSetEmailParameters.h -// OneSignal -// -// Created by Brad Hesse on 2/1/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import #import "OneSignal.h" diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignalSetEmailParameters.m b/iOS_SDK/OneSignalSDK/Source/OneSignalSetEmailParameters.m index 23e32e9a5..933bda356 100644 --- a/iOS_SDK/OneSignalSDK/Source/OneSignalSetEmailParameters.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignalSetEmailParameters.m @@ -1,10 +1,29 @@ -// -// OneSignalSetEmailParameters.m -// OneSignal -// -// Created by Brad Hesse on 2/1/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import "OneSignalSetEmailParameters.h" diff --git a/iOS_SDK/OneSignalSDK/Source/ReattemptRequest.h b/iOS_SDK/OneSignalSDK/Source/ReattemptRequest.h index 2ac3c0a6b..fc872bb58 100644 --- a/iOS_SDK/OneSignalSDK/Source/ReattemptRequest.h +++ b/iOS_SDK/OneSignalSDK/Source/ReattemptRequest.h @@ -1,10 +1,29 @@ -// -// ReattemptRequest.h -// OneSignal -// -// Created by Brad Hesse on 1/31/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import #import "OneSignal.h" diff --git a/iOS_SDK/OneSignalSDK/Source/ReattemptRequest.m b/iOS_SDK/OneSignalSDK/Source/ReattemptRequest.m index 6c9efe872..120108101 100644 --- a/iOS_SDK/OneSignalSDK/Source/ReattemptRequest.m +++ b/iOS_SDK/OneSignalSDK/Source/ReattemptRequest.m @@ -1,10 +1,29 @@ -// -// ReattemptRequest.m -// OneSignal -// -// Created by Brad Hesse on 1/31/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import "ReattemptRequest.h" diff --git a/iOS_SDK/OneSignalSDK/UnitTests/BadgeTests.m b/iOS_SDK/OneSignalSDK/UnitTests/BadgeTests.m new file mode 100644 index 000000000..2b9e2e985 --- /dev/null +++ b/iOS_SDK/OneSignalSDK/UnitTests/BadgeTests.m @@ -0,0 +1,159 @@ +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import "UnitTestCommonMethods.h" +#import "OneSignalExtensionBadgeHandler.h" +#import "NSUserDefaultsOverrider.h" +#import "UNUserNotificationCenterOverrider.h" +#import "UNUserNotificationCenter+OneSignal.h" +#import "OneSignalHelperOverrider.h" +#import "OneSignalHelper.h" + +@interface BadgeTests : XCTestCase + +@end + +@implementation BadgeTests + +- (void)setUp { + [super setUp]; + + OneSignalHelperOverrider.mockIOSVersion = 10; + + [OneSignalUNUserNotificationCenter setUseiOS10_2_workaround:true]; + + UNUserNotificationCenterOverrider.notifTypesOverride = 7; + UNUserNotificationCenterOverrider.authorizationStatus = [NSNumber numberWithInteger:UNAuthorizationStatusAuthorized]; + + [NSUserDefaultsOverrider clearInternalDictionary]; + + [UnitTestCommonMethods clearStateForAppRestart:self]; + + [UnitTestCommonMethods beforeAllTest]; +} +- (void)testBadgeExtensionUpdate { + [OneSignalExtensionBadgeHandler updateCachedBadgeValue:0]; + + //test that manually setting the badge number also updates NSUserDefaults for our app group + [[UIApplication sharedApplication] setApplicationIconBadgeNumber:1]; + + XCTAssert(OneSignalExtensionBadgeHandler.currentCachedBadgeValue == 1); + + NSMutableDictionary * userInfo = [@{ + @"aps": @{ + @"mutable-content": @1, + @"alert": @"Message Body" + }, + @"os_data": @{ + @"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba", + @"badge_inc" : @2 + } + } mutableCopy]; + + UNNotificationResponse *notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; + + //test that receiving a notification with badge_inc updates the badge icon number + [OneSignal didReceiveNotificationExtensionRequest:notifResponse.notification.request withMutableNotificationContent:nil]; + + XCTAssert(OneSignalExtensionBadgeHandler.currentCachedBadgeValue == 3); + + //test that a negative badge_inc value decrements correctly + [userInfo setObject:@{@"badge_inc" : @-1, @"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"} forKey:@"os_data"]; + + UNNotificationResponse *newNotifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; + + [OneSignal didReceiveNotificationExtensionRequest:newNotifResponse.notification.request withMutableNotificationContent:nil]; + + XCTAssert(OneSignalExtensionBadgeHandler.currentCachedBadgeValue == 2); +} + +//tests to make sure that setting the badge works along with incrementing/decrementing +- (void)testSetBadgeExtensionUpdate { + [OneSignalExtensionBadgeHandler updateCachedBadgeValue:0]; + + NSMutableDictionary * userInfo = [@{ + @"aps": @{ + @"mutable-content": @1, + @"alert": @"Message Body", + @"badge" : @54 + }, + @"os_data": @{ + @"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba" + } + } mutableCopy]; + + UNNotificationResponse *notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; + + //test that receiving a notification with badge_inc updates the badge icon number + [OneSignal didReceiveNotificationExtensionRequest:notifResponse.notification.request withMutableNotificationContent:nil]; + + XCTAssert(OneSignalExtensionBadgeHandler.currentCachedBadgeValue == 54); + + [userInfo setObject:@{@"mutable-content" : @1, @"alert" : @"test msg"} forKey:@"aps"]; + [userInfo setObject:@{@"badge_inc" : @-1, @"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba"} forKey:@"os_data"]; + + UNNotificationResponse *newNotifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; + + UNMutableNotificationContent *mutableContent = [newNotifResponse.notification.request.content mutableCopy]; + + //tests to make sure the extension is correctly modifying the badge value of the replacement content + let replacementContent = [OneSignal didReceiveNotificationExtensionRequest:newNotifResponse.notification.request withMutableNotificationContent:mutableContent]; + + XCTAssert([replacementContent.badge intValue] == 53); + + XCTAssert(OneSignalExtensionBadgeHandler.currentCachedBadgeValue == 53); +} + +//tests to make sure that the SDK never tries to set negative badge values +- (void)testDecrementZeroValue { + [OneSignalExtensionBadgeHandler updateCachedBadgeValue:0]; + + NSMutableDictionary * userInfo = [@{ + @"aps": @{ + @"mutable-content": @1, + @"alert": @"Message Body" + }, + @"os_data": @{ + @"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba", + @"badge_inc" : @-5 + } + } mutableCopy]; + + UNNotificationResponse *notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; + + UNMutableNotificationContent *mutableContent = [notifResponse.notification.request.content mutableCopy]; + + //Since the notification is trying to set a negative value, the SDK should keep the badge count == 0 + let replacementContent = [OneSignal didReceiveNotificationExtensionRequest:notifResponse.notification.request withMutableNotificationContent:mutableContent]; + + XCTAssert(replacementContent.badge.intValue == 0); + + XCTAssert(OneSignalExtensionBadgeHandler.currentCachedBadgeValue == 0); +} + +@end diff --git a/iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m b/iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m index f7558a6c3..cbaff32ec 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/EmailTests.m @@ -1,10 +1,29 @@ -// -// EmailTests.m -// UnitTests -// -// Created by Brad Hesse on 1/30/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import #import "OneSignal.h" diff --git a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.h b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.h index 01f8b511f..f2d8db37a 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.h +++ b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.h @@ -1,10 +1,29 @@ -// -// OneSignalClientOverrider.h -// OneSignal -// -// Created by Brad Hesse on 12/19/17. -// Copyright © 2017 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import #import diff --git a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.m b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.m index b60731a17..a9d07bef9 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/OneSignalClientOverrider.m @@ -1,18 +1,29 @@ -// -// OneSignalClientOverrider.m -// OneSignal -// -// Created by Brad Hesse on 12/19/17. -// Copyright © 2017 Hiptic. All rights reserved. -// - -// -// OneSignalClientOverrider.m -// UnitTests -// -// Created by Brad Hesse on 12/18/17. -// Copyright © 2017 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import "OneSignalClientOverrider.h" #import "TestHelperFunctions.h" diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h b/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h index ef8bc1d26..d3e603a02 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.h @@ -1,10 +1,29 @@ -// -// UnitTestCommonMethods.h -// UnitTests -// -// Created by Brad Hesse on 1/30/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import #import diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m b/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m index 19a56c55e..03006bf8b 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m @@ -1,10 +1,29 @@ -// -// UnitTestCommonMethods.m -// UnitTests -// -// Created by Brad Hesse on 1/30/18. -// Copyright © 2018 Hiptic. All rights reserved. -// +/** + * Modified MIT License + * + * Copyright 2017 OneSignal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * 1. The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 2. All copies of substantial portions of the Software may only be used in connection + * with services provided by OneSignal. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #import "UnitTestCommonMethods.h" #import "OneSignalClientOverrider.h" diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m index 3c1e25d28..bc831980a 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m @@ -1811,45 +1811,4 @@ -(void)testDelayedSubscriptionUpdate { XCTAssertTrue(observer->last.to.subscribed); } -- (void)testBadgeExtensionUpdate { - - let defaults = [[NSUserDefaults alloc] initWithSuiteName:[OneSignalExtensionBadgeHandler appGroupName]]; - [defaults setObject:@2 forKey:ONESIGNAL_BADGE_KEY]; - [defaults synchronize]; - - //test that manually setting the badge number also updates NSUserDefaults for our app group - [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0]; - - XCTAssert([(NSNumber *)[defaults objectForKey:ONESIGNAL_BADGE_KEY] isEqualToNumber:@0]); - - NSMutableDictionary * userInfo = [@{ - @"aps": @{ - @"mutable-content": @1, - @"alert": @"Message Body" - }, - @"os_data": @{ - @"i": @"b2f7f966-d8cc-11e4-bed1-df8f05be55ba", - @"buttons": @[@{@"i": @"id1", @"n": @"text1"}], - @"att": @{ @"id": @"http://domain.com/file.jpg" } - }, - @"badge_inc" : @3 - } mutableCopy]; - - id notifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; - - //test that receiving a notification with badge_inc updates the badge icon number - [OneSignal didReceiveNotificationExtensionRequest:[notifResponse notification].request withMutableNotificationContent:nil]; - - XCTAssert([(NSNumber *)[defaults objectForKey:ONESIGNAL_BADGE_KEY] isEqualToNumber:@3]); - - //test that a negative badge_inc value decrements correctly - [userInfo setObject:@-1 forKey:@"badge_inc"]; - - id newNotifResponse = [UnitTestCommonMethods createBasiciOSNotificationResponseWithPayload:userInfo]; - - [OneSignal didReceiveNotificationExtensionRequest:[newNotifResponse notification].request withMutableNotificationContent:nil]; - - XCTAssert([(NSNumber *)[defaults objectForKey:ONESIGNAL_BADGE_KEY] isEqualToNumber:@2]); -} - @end