Skip to content

Commit d8720c1

Browse files
authored
Merge pull request #1229 from OneSignal/fix/new_session_triggering_from_2nd_init
Fix new session triggering from 2nd init
2 parents 8543718 + 7fad04e commit d8720c1

File tree

4 files changed

+76
-14
lines changed

4 files changed

+76
-14
lines changed

OneSignalSDK/onesignal/src/main/java/com/onesignal/OneSignal.java

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,6 @@ synchronized private static void init(Context context) {
692692
if (notificationOpenedHandler != null)
693693
fireCallbackForOpenedNotifications();
694694
logger.debug("OneSignal SDK initialization already completed.");
695-
doSessionInit();
696695
return;
697696
}
698697

@@ -824,21 +823,19 @@ private static void handleAmazonPurchase() {
824823
// If we don't have a OneSignal player_id yet make the call to create it regardless of focus
825824
private static void doSessionInit() {
826825
// Check session time to determine whether to start a new session or not
827-
if (isPastOnSessionTime()) {
828-
if (inForeground) {
829-
logger.debug("Starting new session");
830-
831-
OneSignalStateSynchronizer.setNewSession();
832-
outcomeEventsController.cleanOutcomes();
833-
sessionManager.restartSessionIfNeeded(getAppEntryState());
834-
getInAppMessageController().resetSessionLaunchTime();
835-
setLastSessionTime(time.getCurrentTimeMillis());
836-
}
837-
} else {
838-
logger.debug("Continue on same session");
839-
826+
if (shouldStartNewSession()) {
827+
logger.debug("Starting new session with appEntryState: " + getAppEntryState());
828+
829+
OneSignalStateSynchronizer.setNewSession();
830+
outcomeEventsController.cleanOutcomes();
831+
sessionManager.restartSessionIfNeeded(getAppEntryState());
832+
getInAppMessageController().resetSessionLaunchTime();
833+
setLastSessionTime(time.getCurrentTimeMillis());
834+
} else if (isInForeground()) {
835+
logger.debug("Continue on same session with appEntryState: " + getAppEntryState());
840836
sessionManager.attemptSessionUpgrade(getAppEntryState());
841837
}
838+
842839
getInAppMessageController().initWithCachedInAppMessages();
843840

844841
// We still want register the user to OneSignal if the SDK was initialized
@@ -2914,6 +2911,16 @@ static boolean isAppActive() {
29142911
return initDone && isInForeground();
29152912
}
29162913

2914+
private static boolean shouldStartNewSession() {
2915+
if (!isInForeground())
2916+
return false;
2917+
2918+
if (!isPastOnSessionTime())
2919+
return false;
2920+
2921+
return true;
2922+
}
2923+
29172924
private static boolean isPastOnSessionTime() {
29182925
long currentTimeMillis = OneSignal.getTime().getCurrentTimeMillis();
29192926
long lastSessionTime = getLastSessionTime();

OneSignalSDK/unittest/src/test/java/com/onesignal/OneSignalPackagePrivateHelper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
public class OneSignalPackagePrivateHelper {
2929
public static final String IN_APP_MESSAGES_JSON_KEY = com.onesignal.OSInAppMessageController.IN_APP_MESSAGES_JSON_KEY;
3030

31+
public static final long MIN_ON_SESSION_TIME_MILLIS = com.onesignal.OneSignal.MIN_ON_SESSION_TIME_MILLIS;
32+
3133
private static abstract class RunnableArg<T> {
3234
abstract void run(T object) throws Exception;
3335
}

OneSignalSDK/unittest/src/test/java/com/test/onesignal/OneSignalInitializationIntegrationTestsRunner.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import androidx.test.core.app.ApplicationProvider;
44

5+
import com.onesignal.MockOSTimeImpl;
56
import com.onesignal.OneSignal;
67
import com.onesignal.ShadowCustomTabsClient;
78
import com.onesignal.ShadowCustomTabsSession;
@@ -21,7 +22,10 @@
2122
import org.robolectric.annotation.Config;
2223
import org.robolectric.shadows.ShadowLog;
2324

25+
import static com.onesignal.OneSignalPackagePrivateHelper.MIN_ON_SESSION_TIME_MILLIS;
26+
import static com.onesignal.OneSignalPackagePrivateHelper.OneSignal_setTime;
2427
import static com.onesignal.ShadowOneSignalRestClient.setRemoteParamsGetHtmlResponse;
28+
import static com.test.onesignal.RestClientAsserts.assertNumberOfOnSessions;
2529
import static com.test.onesignal.TestHelpers.threadAndTaskWait;
2630

2731
@Config(
@@ -39,6 +43,7 @@
3943
@RunWith(RobolectricTestRunner.class)
4044
public class OneSignalInitializationIntegrationTestsRunner {
4145
private ActivityController<BlankActivity> blankActivityController;
46+
private MockOSTimeImpl time;
4247

4348
@BeforeClass // Runs only once, before any tests
4449
public static void setUpClass() throws Exception {
@@ -52,12 +57,23 @@ public void beforeEachTest() throws Exception {
5257
TestHelpers.beforeTestInitAndCleanup();
5358
setRemoteParamsGetHtmlResponse();
5459
blankActivityController = Robolectric.buildActivity(BlankActivity.class).create();
60+
61+
time = new MockOSTimeImpl();
62+
OneSignal_setTime(time);
5563
}
5664

65+
private static final long MIN_ON_SESSION_TIME_SEC = MIN_ON_SESSION_TIME_MILLIS / 1_000L;
5766
private static final String APP_ID = "11111111-2222-3333-4444-55555555555";
5867
private static void helper_OneSignal_initWithAppContext() {
5968
OneSignal.initWithContext(ApplicationProvider.getApplicationContext());
6069
}
70+
private void helper_OneSignal_initWithActivity() {
71+
OneSignal.initWithContext(blankActivityController.get());
72+
}
73+
74+
private void helper_advanceSystemTimeToNextOnSession() {
75+
time.advanceSystemAndElapsedTimeBy(MIN_ON_SESSION_TIME_SEC + 1);
76+
}
6177

6278
@Test
6379
public void setRequiresUserPrivacyConsent_withTrue_CalledFirst_DoesNOTCreatePlayer() throws Exception {
@@ -82,4 +98,27 @@ public void setRequiresUserPrivacyConsent_withFalseAndRemoteTrue_DoesNOTCreatePl
8298
RestClientAsserts.assertRemoteParamsWasTheOnlyNetworkCall();
8399
}
84100

101+
/**
102+
* on_session calls should only be made if the user left the app for MIN_ON_SESSION_TIME_SEC or longer
103+
* This test ensures that we meet the out of focus requirement, at lest through initWithContext
104+
* being called a 2nd time code path.
105+
*/
106+
@Test
107+
public void initWithContext_calledA2ndTimeAfter30OrMoreSeconds_doesNotStartNewSession() throws Exception {
108+
// 1. Basic OneSignal init with Activity
109+
OneSignal.setAppId(APP_ID);
110+
helper_OneSignal_initWithActivity();
111+
threadAndTaskWait();
112+
113+
// 2. Keep the app in focus for 30+ seconds, which is the time required to
114+
helper_advanceSystemTimeToNextOnSession();
115+
116+
// 3. Developer or OneSignal internally calls OneSignal.initWithContext
117+
helper_OneSignal_initWithActivity();
118+
threadAndTaskWait();
119+
120+
// 4. Ensure we do NOT make an /players/{player_id}/on_session network call.
121+
assertNumberOfOnSessions(0);
122+
}
123+
85124
}

OneSignalSDK/unittest/src/test/java/com/test/onesignal/RestClientAsserts.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,18 @@ static void assertOnSessionAtIndex(int index) {
113113
assertOnSessionUrl(request.url);
114114
}
115115

116+
static void assertNumberOfOnSessions(int number) {
117+
int successfulAsserts = 0;
118+
for (Request request : ShadowOneSignalRestClient.requests) {
119+
try {
120+
assertOnSessionUrl(request.url);
121+
successfulAsserts++;
122+
} catch (AssertionError ignored) { }
123+
}
124+
125+
assertEquals(number, successfulAsserts);
126+
}
127+
116128
static void assertOnFocusAtIndex(int index, int focusTimeSec) throws JSONException {
117129
assertOnFocusAtIndex(index, new JSONObject().put("active_time", focusTimeSec));
118130
}
@@ -256,6 +268,8 @@ static void assertOnFocusUrlWithPlayerId(@NonNull String url, @NonNull String id
256268
static void assertOnSessionUrl(String url) {
257269
String[] parts = url.split("/");
258270
assertEquals("players", parts[0]);
271+
if (parts.length == 1)
272+
fail("Not an on_session as player_id and on_session is missing from the URL");
259273
assertIsUUID(parts[1]);
260274
assertEquals("on_session", parts[2]);
261275
}

0 commit comments

Comments
 (0)