diff --git a/iOS_SDK/OneSignalSDK/Source/OneSignal.m b/iOS_SDK/OneSignalSDK/Source/OneSignal.m index bbad63585..109a228d1 100755 --- a/iOS_SDK/OneSignalSDK/Source/OneSignal.m +++ b/iOS_SDK/OneSignalSDK/Source/OneSignal.m @@ -1561,12 +1561,15 @@ + (BOOL)shouldRegisterNow { return false; // Don't make a 2nd on_session if have in inflight one + onesignal_Log(ONE_S_LL_VERBOSE, [NSString stringWithFormat:@"shouldRegisterNow:waitingForOneSReg: %d", waitingForOneSReg]); if (waitingForOneSReg) return false; + onesignal_Log(ONE_S_LL_VERBOSE, [NSString stringWithFormat:@"shouldRegisterNow:isImmediatePlayerCreateOrOnSession: %d", [self isImmediatePlayerCreateOrOnSession]]); if ([self isImmediatePlayerCreateOrOnSession]) return true; + onesignal_Log(ONE_S_LL_VERBOSE, [NSString stringWithFormat:@"shouldRegisterNow:isOnSessionSuccessfulForCurrentState: %d", isOnSessionSuccessfulForCurrentState]); if (isOnSessionSuccessfulForCurrentState) return false; @@ -1587,6 +1590,7 @@ + (BOOL)shouldRegisterNow { } + (void)registerUserAfterDelay { + [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registerUserAfterDelay"]; [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(registerUser) object:nil]; [OneSignalHelper performSelector:@selector(registerUser) onMainThreadOnObject:self withObject:nil afterDelay:reattemptRegistrationInterval]; } @@ -1601,11 +1605,8 @@ + (void)registerUser { // return if the user has not granted privacy permissions if ([self shouldLogMissingPrivacyConsentErrorWithMethodName:nil]) return; - - // We should delay registration if we are waiting on APNS - // But if APNS hasn't responded within 30 seconds, - // we should continue and register the user. - if (waitingForApnsResponse && initializationTime && [[NSDate date] timeIntervalSinceDate:initializationTime] < maxApnsWait) { + + if ([self shouldRegisterUserAfterDelay]) { [self registerUserAfterDelay]; return; } @@ -1613,9 +1614,35 @@ + (void)registerUser { if (!serialQueue) serialQueue = dispatch_queue_create("com.onesignal.regiseruser", DISPATCH_QUEUE_SERIAL); - dispatch_async(serialQueue, ^{ + [self registerUserNow]; +} + ++(void)registerUserNow { + [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registerUserNow"]; + + if (!serialQueue) + serialQueue = dispatch_queue_create("com.onesignal.regiseruser", DISPATCH_QUEUE_SERIAL); + + dispatch_async(serialQueue, ^{ [self registerUserInternal]; - }); + }); +} + +// We should delay registration if we are waiting on APNS +// But if APNS hasn't responded within 30 seconds (maxApnsWait), +// we should continue and register the user. ++ (BOOL)shouldRegisterUserAfterDelay { + [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"registerUser:waitingForApnsResponse: %d", waitingForApnsResponse]]; + [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"registerUser:initializationTime: %@", initializationTime]]; + + // If there isn't an initializationTime yet then the SDK hasn't finished initializing so we should delay + if (!initializationTime) + return true; + + if (!waitingForApnsResponse) + return false; + + return [[NSDate date] timeIntervalSinceDate:initializationTime] < maxApnsWait; } + (OSUserState *)createUserState { @@ -1697,6 +1724,7 @@ + (OSUserState *)createUserState { } + (void)registerUserInternal { + [OneSignal onesignal_Log:ONE_S_LL_VERBOSE message:@"registerUserInternal"]; _registerUserFinished = false; // return if the user has not granted privacy permissions diff --git a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/UIApplicationOverrider.m b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/UIApplicationOverrider.m index 311cdc3e8..368b4240f 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/Shadows/UIApplicationOverrider.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/Shadows/UIApplicationOverrider.m @@ -101,7 +101,7 @@ + (void)setDidFailRegistarationErrorCode:(NSInteger)value { } + (void)setBlockApnsResponse:(BOOL)block { - blockApnsResponse = true; + blockApnsResponse = block; } + (void)setAPNSTokenLength:(int)tokenLength { diff --git a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m index 7d7348703..dee14b2ee 100644 --- a/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m +++ b/iOS_SDK/OneSignalSDK/UnitTests/UnitTests.m @@ -716,6 +716,35 @@ - (void)testPromptedButNeveranswerNotificationPrompt { XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequest[@"notification_types"], @-19); } +// This test covers migrating to OneSignal with the following senario; +// 1. App was released publicly to the AppStore with push on with another provider. +// 2. User imports all existing push tokens into OneSignal. +// 3. OneSignal is added to their app. +// 4. Ensure that identifier is always send with the player create, to prevent duplicated players +- (void)testNotificationPermissionsAcceptedBeforeAddingOneSiganl_waitsForAPNSTokenBeforePlayerCreate { + // 1. Set that notification permissions are already enabled. + UNUserNotificationCenterOverrider.notifTypesOverride = 7; + UNUserNotificationCenterOverrider.authorizationStatus = [NSNumber numberWithInteger:UNAuthorizationStatusAuthorized]; + + // 2. Setup delay of APNs reaponse + [UIApplicationOverrider setBlockApnsResponse:true]; + + // 3. Init OneSignal + [UnitTestCommonMethods initOneSignal_andThreadWait]; + [NSObjectOverrider runPendingSelectors]; + + // 4. Don't make a network call right away + XCTAssertNil(OneSignalClientOverrider.lastHTTPRequest); + + // 5. Simulate APNs now giving us a push token + [UIApplicationOverrider setBlockApnsResponse:false]; + [UnitTestCommonMethods runBackgroundThreads]; + + // 6. Ensure we registered with push token and it has the correct notification_types + XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequest[@"notification_types"], @15); + XCTAssertEqualObjects(OneSignalClientOverrider.lastHTTPRequest[@"identifier"], @"0000000000000000000000000000000000000000000000000000000000000000"); +} + - (void)testNotificationTypesWhenAlreadyAcceptedWithAutoPromptOffOnFristStartPreIos10 { OneSignalHelperOverrider.mockIOSVersion = 9; [UnitTestCommonMethods setCurrentNotificationPermission:true];