Skip to content

Commit 32d9c09

Browse files
authored
Added null check for notificationId to fix issue #590 (#592)
* Created check for notificationId to fix #590 * Some notificationIds are coming through as null * Most likely non-OneSignal notifications slipping through and causing a crash when adding the null notificationId to the received notificationId array * Added a null check and unit test to make sure no null or blank string notificationIds are tracked for confirmed deliveries and outcomes * We will now clean any notifications with invalid notification ids * Each time we go to get the indirect notifications we must iterate over the cached received notifications * While we iterate we clean the array as well and save once done
1 parent dae43ed commit 32d9c09

File tree

6 files changed

+66
-18
lines changed

6 files changed

+66
-18
lines changed

iOS_SDK/OneSignalSDK/Source/OSOutcomesUtils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949

5050
// Methods for received notification ids within the notification limit and attribution window
5151
+ (NSArray *)getCachedReceivedNotifications;
52-
+ (void)saveReceivedNotificationFromBackground:(NSString *)notificationId;
52+
+ (void)saveReceivedNotifications:(NSArray *)notifications;
53+
+ (void)saveReceivedNotificationFromBackground:(NSString * _Nonnull)notificationId;
5354

5455
@end

iOS_SDK/OneSignalSDK/Source/OSOutcomesUtils.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ + (void)saveReceivedNotifications:(NSArray *)notifications {
149149
/*
150150
Saves a received indirect notification into the NSUSerDefaults at a limit equivalent to the indirect notification limit param
151151
*/
152-
+ (void)saveReceivedNotificationFromBackground:(NSString * _Nullable)notificationId {
152+
+ (void)saveReceivedNotificationFromBackground:(NSString * _Nonnull)notificationId {
153153
[OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"saveReceivedNotificationFromBackground notificationId: %@",
154154
notificationId]];
155155

iOS_SDK/OneSignalSDK/Source/OneSignalNotificationServiceExtensionHandler.m

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,13 @@ + (UNMutableNotificationContent*)didReceiveNotificationExtensionRequest:(UNNotif
5050
// Track receieved
5151
[OneSignalTrackFirebaseAnalytics trackReceivedEvent:payload];
5252

53-
// Track Receive Receipt
54-
[OneSignal.receiveReceiptsController sendReceiveReceiptWithNotificationId:payload.notificationID];
55-
56-
// Save receieved notification id
57-
[OSOutcomesUtils saveReceivedNotificationFromBackground:payload.notificationID];
53+
let receivedNotificationId = payload.notificationID;
54+
if (receivedNotificationId && ![receivedNotificationId isEqualToString:@""]) {
55+
// Track confirmed delivery
56+
[OneSignal.receiveReceiptsController sendReceiveReceiptWithNotificationId:receivedNotificationId];
57+
// Save received notification id
58+
[OSOutcomesUtils saveReceivedNotificationFromBackground:receivedNotificationId];
59+
}
5860

5961
// Action Buttons
6062
[self addActionButtonsToExtentionRequest:request

iOS_SDK/OneSignalSDK/Source/OneSignalSessionManager.m

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,22 +204,27 @@ - (OSSessionResult *)getSessionResult {
204204
Get the current notifications ids that influenced the session
205205
*/
206206
- (NSArray *)getIndirectNotificationIds {
207-
NSArray *receivedNotifications = [OSOutcomesUtils getCachedReceivedNotifications];
208-
if (!receivedNotifications || [receivedNotifications count] == 0)
209-
// Unattributed session
210-
return nil;
207+
NSMutableArray *receivedNotifications = [[NSMutableArray alloc] initWithArray:[OSOutcomesUtils getCachedReceivedNotifications]];
208+
if (!receivedNotifications || receivedNotifications.count == 0)
209+
return nil; // Unattributed session
211210

212211
NSMutableArray *notificationsIds = [NSMutableArray new];
213212
NSInteger attributionWindowInSeconds = [OSOutcomesUtils getIndirectAttributionWindow] * 60;
214213
NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];
215214

216-
for (OSIndirectNotification *notification in receivedNotifications) {
217-
long difference = currentTime - notification.timestamp;
218-
if (difference <= attributionWindowInSeconds) {
219-
[notificationsIds addObject:notification.notificationId];
215+
// Add only valid notifications within the attribution window
216+
for (var i = 0; i < receivedNotifications.count; i++) {
217+
OSIndirectNotification* notification = [receivedNotifications objectAtIndex:i];
218+
if (notification.notificationId && ![notification.notificationId isEqualToString:@""]) {
219+
long difference = currentTime - notification.timestamp;
220+
if (difference <= attributionWindowInSeconds)
221+
[notificationsIds addObject:notification.notificationId];
220222
}
223+
else
224+
[receivedNotifications removeObjectAtIndex:i--];
221225
}
222-
226+
// Cache updated notifications as received, this removes notifications with invalid notification ids
227+
[OSOutcomesUtils saveReceivedNotifications:receivedNotifications.copy];
223228
return notificationsIds;
224229
}
225230

iOS_SDK/OneSignalSDK/UnitTests/OutcomeIntegrationTests.m

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,42 @@ - (void)testDirectSession_overridesIndirectSession_andSendsOnFocus {
198198
XCTAssertEqualObjects(OneSignal.sessionManager.getNotificationIds, @[@"test_notification_2"]);
199199
}
200200

201+
- (void)testSavingNullReceivedNotificationId {
202+
// 1. Open app
203+
[UnitTestCommonMethods initOneSignalAndThreadWait];
204+
205+
// 2. Close the app for 31 seconds
206+
[UnitTestCommonMethods backgroundApp];
207+
[NSDateOverrider advanceSystemTimeBy:31];
208+
209+
// 3. Receive 2 notifications, one blank id and one null id
210+
[UnitTestCommonMethods receiveNotification:@"" wasOpened:NO];
211+
[UnitTestCommonMethods receiveNotification:nil wasOpened:NO];
212+
213+
// 4. Open app
214+
[UnitTestCommonMethods foregroundApp];
215+
[UnitTestCommonMethods initOneSignalAndThreadWait];
216+
217+
// 5. Make sure the session is UNATTRIBUTED and has 0 notifications
218+
XCTAssertEqual(OneSignal.sessionManager.getSession, UNATTRIBUTED);
219+
XCTAssertEqual(OneSignal.sessionManager.getNotificationIds.count, 0);
220+
221+
// 6. Close the app for 31 seconds
222+
[UnitTestCommonMethods backgroundApp];
223+
[NSDateOverrider advanceSystemTimeBy:31];
224+
225+
// 7. Receive 1 notification
226+
[UnitTestCommonMethods receiveNotification:@"test_notification_1" wasOpened:NO];
227+
228+
// 8. Open app
229+
[UnitTestCommonMethods foregroundApp];
230+
[UnitTestCommonMethods initOneSignalAndThreadWait];
231+
232+
// 9. Make sure the session is INDIRECT and has 1 notifications
233+
XCTAssertEqual(OneSignal.sessionManager.getSession, INDIRECT);
234+
XCTAssertEqual(OneSignal.sessionManager.getNotificationIds.count, 1);
235+
}
236+
201237
- (void)testIndirectSession_afterReceiveingNotifications {
202238
// 1. Open app
203239
[UnitTestCommonMethods initOneSignalAndThreadWait];

iOS_SDK/OneSignalSDK/UnitTests/UnitTestCommonMethods.m

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,10 @@ + (void)answerNotificationPrompt:(BOOL)accept {
263263
+ (void)receiveNotification:(NSString *)notificationId wasOpened:(BOOL)opened {
264264
// Create notification content
265265
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
266+
267+
if (!notificationId)
268+
notificationId = @"";
269+
266270
content.userInfo = [self createNotificationUserInfo:notificationId];
267271

268272
// Create notification request
@@ -271,10 +275,10 @@ + (void)receiveNotification:(NSString *)notificationId wasOpened:(BOOL)opened {
271275
// Entry point for the NSE
272276
[OneSignalNotificationServiceExtensionHandler didReceiveNotificationExtensionRequest:request withMutableNotificationContent:content];
273277

274-
[self handleNotificationReceived:notificationId messageDict:content.userInfo wasOpened:opened];
278+
[self handleNotificationReceived:content.userInfo wasOpened:opened];
275279
}
276280

277-
+ (void)handleNotificationReceived:(NSString*)notificationId messageDict:(NSDictionary*)messageDict wasOpened:(BOOL)opened {
281+
+ (void)handleNotificationReceived:(NSDictionary*)messageDict wasOpened:(BOOL)opened {
278282
BOOL foreground = UIApplication.sharedApplication.applicationState != UIApplicationStateBackground;
279283
BOOL isActive = UIApplication.sharedApplication.applicationState == UIApplicationStateActive;
280284

0 commit comments

Comments
 (0)