Skip to content

Commit 4678ff6

Browse files
committed
Fix ANR due to on_focus call being call from MainThread
* When attempSessionUpgrade is call, onFocus call can end being call from mainThread * Add MainThread check on makeRequest * Throw RuntimeException when running network calls from MainThread * For testing Shadow OSUtils isThreadRunningOnMainThread
1 parent 397e2c1 commit 4678ff6

File tree

7 files changed

+57
-24
lines changed

7 files changed

+57
-24
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,10 @@ protected void saveInfluences(List<OSInfluence> influences) {
173173
protected boolean timeTypeApplies(@NonNull List<OSInfluence> influences) {
174174
for (OSInfluence influence : influences) {
175175
// Is true is at least one channel attributed the session
176-
if (influence.getInfluenceType().isAttributed())
176+
if (influence.getInfluenceType().isAttributed()) {
177+
OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, this.getClass().getSimpleName() + ":timeTypeApplies for influences: " + influences.toString() + " true");
177178
return true;
179+
}
178180
}
179181
return false;
180182
}

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.onesignal;
22

3+
import android.os.Process;
34
import android.support.annotation.NonNull;
45
import android.support.annotation.Nullable;
56

@@ -24,6 +25,8 @@
2425
*/
2526
public class OSSessionManager {
2627

28+
private static final String OS_END_CURRENT_SESSION = "OS_END_CURRENT_SESSION";
29+
2730
public interface SessionListener {
2831
// Fire with the last OSInfluence that just ended.
2932
void onSessionEnding(@NonNull List<OSInfluence> lastInfluences);
@@ -234,10 +237,17 @@ private boolean willChangeSession(@NonNull OSChannelTracker channelTracker,
234237
!JSONUtils.compareJSONArrays(channelTracker.getIndirectIds(), indirectNotificationIds);
235238
}
236239

237-
private void sendSessionEndingWithInfluences(List<OSInfluence> endingInfluences) {
240+
private void sendSessionEndingWithInfluences(final List<OSInfluence> endingInfluences) {
238241
logger.debug("OneSignal SessionManager sendSessionEndingWithInfluences with influences: " + endingInfluences);
239242
// Only end session if there are influences available to end
240-
if (endingInfluences.size() > 0)
241-
sessionListener.onSessionEnding(endingInfluences);
243+
if (endingInfluences.size() > 0) {
244+
new Thread(new Runnable() {
245+
@Override
246+
public void run() {
247+
Thread.currentThread().setPriority(Process.THREAD_PRIORITY_BACKGROUND);
248+
sessionListener.onSessionEnding(endingInfluences);
249+
}
250+
}, OS_END_CURRENT_SESSION).start();
251+
}
242252
}
243253
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,10 @@ static boolean areNotificationsEnabled(Context context) {
475475
return true;
476476
}
477477

478+
static boolean isRunningOnMainThread() {
479+
return Thread.currentThread().equals(Looper.getMainLooper().getThread());
480+
}
481+
478482
static void runOnMainUIThread(Runnable runnable) {
479483
if (Looper.getMainLooper().getThread() == Thread.currentThread())
480484
runnable.run();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ static boolean isForeground() {
437437
@Override
438438
public void onSessionEnding(@NonNull List<OSInfluence> lastInfluences) {
439439
if (outcomeEventsController == null)
440-
OneSignal.Log(LOG_LEVEL.WARN, "OneSignal onSessionEnding called before initZ");
440+
OneSignal.Log(LOG_LEVEL.WARN, "OneSignal onSessionEnding called before init!");
441441
if (outcomeEventsController != null)
442442
outcomeEventsController.cleanOutcomes();
443443
FocusTimeController.getInstance().onSessionEnded(lastInfluences);

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,13 @@ public static void postSync(String url, JSONObject jsonBody, ResponseHandler res
100100
}
101101

102102
private static void makeRequest(final String url, final String method, final JSONObject jsonBody, final ResponseHandler responseHandler, final int timeout, final String cacheKey) {
103+
if (OSUtils.isRunningOnMainThread())
104+
throw new OneSignalNetworkCallException("Method: " + method + " was called from the Main Thread!");
105+
103106
// If not a GET request, check if the user provided privacy consent if the application is set to require user privacy consent
104107
if (method != null && OneSignal.shouldLogUserPrivacyConsentErrorMessageForMethodName(null))
105108
return;
106-
109+
107110
final Thread[] callbackThread = new Thread[1];
108111
Thread connectionThread = new Thread(new Runnable() {
109112
public void run() {
@@ -289,4 +292,10 @@ public void run() {
289292
private static HttpURLConnection newHttpURLConnection(String url) throws IOException {
290293
return (HttpURLConnection)new URL(BASE_URL + url).openConnection();
291294
}
295+
296+
private static class OneSignalNetworkCallException extends RuntimeException {
297+
public OneSignalNetworkCallException(String message) {
298+
super(message);
299+
}
300+
}
292301
}

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757

5858
@RunWith(RobolectricTestRunner.class)
5959
public class RESTClientRunner {
60-
60+
6161
@BeforeClass // Runs only once, before any tests
6262
public static void setUpClass() throws Exception {
6363
ShadowLog.stream = System.out;
@@ -82,7 +82,7 @@ public void testRESTClientFallbackTimeout() throws Exception {
8282
mockThreadHang = true;
8383
}};
8484

85-
OneSignalRestClient.getSync("URL", null,"");
85+
OneSignalRestClient.get("URL", null, "");
8686
threadAndTaskWait();
8787

8888
assertTrue(ShadowOneSignalRestClientWithMockConnection.lastConnection.getDidInterruptMockHang());
@@ -92,23 +92,23 @@ public void testRESTClientFallbackTimeout() throws Exception {
9292

9393
@Test
9494
public void SDKHeaderIsIncludedInGetCalls() throws Exception {
95-
OneSignalRestClient.getSync("URL", null, null);
95+
OneSignalRestClient.get("URL", null, null);
9696
threadAndTaskWait();
9797

9898
assertEquals(SDK_VERSION_HTTP_HEADER, getLastHTTPHeaderProp("SDK-Version"));
9999
}
100100

101101
@Test
102102
public void SDKHeaderIsIncludedInPostCalls() throws Exception {
103-
OneSignalRestClient.postSync("URL", null,null);
103+
OneSignalRestClient.post("URL", null, null);
104104
threadAndTaskWait();
105105

106106
assertEquals(SDK_VERSION_HTTP_HEADER, getLastHTTPHeaderProp("SDK-Version"));
107107
}
108108

109109
@Test
110110
public void SDKHeaderIsIncludedInPutCalls() throws Exception {
111-
OneSignalRestClient.putSync("URL", null,null);
111+
OneSignalRestClient.put("URL", null, null);
112112
threadAndTaskWait();
113113

114114
assertEquals(SDK_VERSION_HTTP_HEADER, getLastHTTPHeaderProp("SDK-Version"));
@@ -131,7 +131,7 @@ public void testReusesCache() throws Exception {
131131
responseBody = "{\"key1\": \"value1\"}";
132132
mockProps.put("etag", MOCK_ETAG_VALUE);
133133
}};
134-
OneSignalRestClient.getSync("URL", new OneSignalRestClient.ResponseHandler() {
134+
OneSignalRestClient.get("URL", new OneSignalRestClient.ResponseHandler() {
135135
@Override
136136
public void onSuccess(String response) {
137137
firstResponse = response;
@@ -145,7 +145,7 @@ public void onSuccess(String response) {
145145
status = 304;
146146
}};
147147

148-
OneSignalRestClient.getSync("URL", new OneSignalRestClient.ResponseHandler() {
148+
OneSignalRestClient.get("URL", new OneSignalRestClient.ResponseHandler() {
149149
@Override
150150
public void onSuccess(String response) {
151151
secondResponse = response;
@@ -171,15 +171,15 @@ public void testReplacesCacheOn200() throws Exception {
171171
responseBody = newMockResponse;
172172
mockProps.put("etag", "MOCK_ETAG_VALUE2");
173173
}};
174-
OneSignalRestClient.getSync("URL", null, MOCK_CACHE_KEY);
174+
OneSignalRestClient.get("URL", null, MOCK_CACHE_KEY);
175175
threadAndTaskWait();
176176
Thread.sleep(200);
177177

178178
// 4. Make 4th request and make sure we get the new cached value
179179
ShadowOneSignalRestClientWithMockConnection.mockResponse = new MockHttpURLConnection.MockResponse() {{
180180
status = 304;
181181
}};
182-
OneSignalRestClient.getSync("URL", new OneSignalRestClient.ResponseHandler() {
182+
OneSignalRestClient.get("URL", new OneSignalRestClient.ResponseHandler() {
183183
@Override
184184
public void onSuccess(String response) {
185185
secondResponse = response.replace("\u0000", "");
@@ -203,7 +203,7 @@ public void testApiCall400Response() throws Exception {
203203

204204
final String[] failResponse = {null};
205205
final int[] statusCodeResponse = {0};
206-
OneSignalRestClient.postSync("URL", null, new OneSignalRestClient.ResponseHandler() {
206+
OneSignalRestClient.post("URL", null, new OneSignalRestClient.ResponseHandler() {
207207
@Override
208208
public void onSuccess(String response) {
209209
super.onSuccess(response);
@@ -234,7 +234,7 @@ public void testApiCall400EmptyResponse() throws Exception {
234234

235235
final String[] failResponse = {null};
236236
final int[] statusCodeResponse = {0};
237-
OneSignalRestClient.postSync("URL", null, new OneSignalRestClient.ResponseHandler() {
237+
OneSignalRestClient.post("URL", null, new OneSignalRestClient.ResponseHandler() {
238238
@Override
239239
public void onSuccess(String response) {
240240
super.onSuccess(response);

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ public void testDirectWithEmptyNotification() {
339339
}
340340

341341
@Test
342-
public void testSessionUpgradeFromAppClosed() {
342+
public void testSessionUpgradeFromAppClosed() throws Exception {
343343
trackerFactory.saveInfluenceParams(new OneSignalPackagePrivateHelper.RemoteOutcomeParams());
344344
sessionManager.initSessionFromCache();
345345

@@ -369,6 +369,7 @@ public void testSessionUpgradeFromAppClosed() {
369369
}
370370

371371
sessionManager.attemptSessionUpgrade(OneSignal.AppEntryAction.APP_CLOSE);
372+
threadAndTaskWait();
372373

373374
influences = sessionManager.getInfluences();
374375

@@ -390,7 +391,7 @@ public void testSessionUpgradeFromAppClosed() {
390391
}
391392

392393
@Test
393-
public void testSessionUpgradeFromUnattributedToIndirect() throws JSONException {
394+
public void testSessionUpgradeFromUnattributedToIndirect() throws Exception {
394395
trackerFactory.saveInfluenceParams(new OneSignalPackagePrivateHelper.RemoteOutcomeParams());
395396
sessionManager.initSessionFromCache();
396397

@@ -420,6 +421,7 @@ public void testSessionUpgradeFromUnattributedToIndirect() throws JSONException
420421
}
421422

422423
sessionManager.attemptSessionUpgrade(OneSignal.AppEntryAction.APP_OPEN);
424+
threadAndTaskWait();
423425

424426
influences = sessionManager.getInfluences();
425427

@@ -439,7 +441,7 @@ public void testSessionUpgradeFromUnattributedToIndirect() throws JSONException
439441
}
440442

441443
@Test
442-
public void testSessionUpgradeFromUnattributedToDirectNotification() throws JSONException {
444+
public void testSessionUpgradeFromUnattributedToDirectNotification() throws Exception {
443445
trackerFactory.saveInfluenceParams(new OneSignalPackagePrivateHelper.RemoteOutcomeParams());
444446
sessionManager.initSessionFromCache();
445447

@@ -452,6 +454,7 @@ public void testSessionUpgradeFromUnattributedToDirectNotification() throws JSON
452454
sessionManager.onNotificationReceived(GENERIC_ID);
453455
sessionManager.onInAppMessageReceived(GENERIC_ID);
454456
sessionManager.onDirectInfluenceFromNotificationOpen(GENERIC_ID);
457+
threadAndTaskWait();
455458

456459
iamInfluences = trackerFactory.getIAMChannelTracker().getCurrentSessionInfluence();
457460
notificationInfluences = trackerFactory.getNotificationChannelTracker().getCurrentSessionInfluence();
@@ -474,7 +477,7 @@ public void testSessionUpgradeFromUnattributedToDirectNotification() throws JSON
474477
}
475478

476479
@Test
477-
public void testSessionUpgradeFromIndirectToDirect() throws JSONException {
480+
public void testSessionUpgradeFromIndirectToDirect() throws Exception {
478481
trackerFactory.saveInfluenceParams(new OneSignalPackagePrivateHelper.RemoteOutcomeParams());
479482
sessionManager.initSessionFromCache();
480483

@@ -490,6 +493,7 @@ public void testSessionUpgradeFromIndirectToDirect() throws JSONException {
490493
assertEquals(GENERIC_ID, notificationInfluences.getIds().get(0));
491494

492495
sessionManager.onDirectInfluenceFromNotificationOpen(NOTIFICATION_ID);
496+
threadAndTaskWait();
493497

494498
iamInfluences = trackerFactory.getIAMChannelTracker().getCurrentSessionInfluence();
495499
notificationInfluences = trackerFactory.getNotificationChannelTracker().getCurrentSessionInfluence();
@@ -513,7 +517,7 @@ public void testSessionUpgradeFromIndirectToDirect() throws JSONException {
513517
}
514518

515519
@Test
516-
public void testSessionUpgradeFromDirectToDirectDifferentID() throws JSONException {
520+
public void testSessionUpgradeFromDirectToDirectDifferentID() throws Exception {
517521
trackerFactory.saveInfluenceParams(new OneSignalPackagePrivateHelper.RemoteOutcomeParams());
518522
sessionManager.initSessionFromCache();
519523

@@ -527,6 +531,7 @@ public void testSessionUpgradeFromDirectToDirectDifferentID() throws JSONExcepti
527531

528532
sessionManager.onNotificationReceived(NOTIFICATION_ID);
529533
sessionManager.onDirectInfluenceFromNotificationOpen(NOTIFICATION_ID);
534+
threadAndTaskWait();
530535

531536
notificationInfluences = trackerFactory.getNotificationChannelTracker().getCurrentSessionInfluence();
532537

@@ -543,7 +548,7 @@ public void testSessionUpgradeFromDirectToDirectDifferentID() throws JSONExcepti
543548
}
544549

545550
@Test
546-
public void testSessionUpgradeFromDirectToDirectSameID() throws JSONException {
551+
public void testSessionUpgradeFromDirectToDirectSameID() throws Exception {
547552
trackerFactory.saveInfluenceParams(new OneSignalPackagePrivateHelper.RemoteOutcomeParams());
548553
sessionManager.initSessionFromCache();
549554

@@ -556,6 +561,7 @@ public void testSessionUpgradeFromDirectToDirectSameID() throws JSONException {
556561
assertEquals(GENERIC_ID, notificationInfluences.getIds().get(0));
557562

558563
sessionManager.attemptSessionUpgrade(OneSignal.AppEntryAction.NOTIFICATION_CLICK);
564+
threadAndTaskWait();
559565

560566
notificationInfluences = trackerFactory.getNotificationChannelTracker().getCurrentSessionInfluence();
561567

@@ -571,14 +577,15 @@ public void testSessionUpgradeFromDirectToDirectSameID() throws JSONException {
571577
}
572578

573579
@Test
574-
public void testSessionUpgradeFromDirectToDirectEndChannelsDirect() throws JSONException {
580+
public void testSessionUpgradeFromDirectToDirectEndChannelsDirect() throws Exception {
575581
trackerFactory.saveInfluenceParams(new OneSignalPackagePrivateHelper.RemoteOutcomeParams());
576582
sessionManager.initSessionFromCache();
577583

578584
sessionManager.onNotificationReceived(GENERIC_ID);
579585
sessionManager.onDirectInfluenceFromNotificationOpen(GENERIC_ID);
580586
sessionManager.onInAppMessageReceived(IAM_ID);
581587
sessionManager.onDirectInfluenceFromIAMClick(IAM_ID);
588+
threadAndTaskWait();
582589

583590
OSInfluence iamInfluences = trackerFactory.getIAMChannelTracker().getCurrentSessionInfluence();
584591
OSInfluence notificationInfluences = trackerFactory.getNotificationChannelTracker().getCurrentSessionInfluence();
@@ -589,6 +596,7 @@ public void testSessionUpgradeFromDirectToDirectEndChannelsDirect() throws JSONE
589596
assertEquals(GENERIC_ID, notificationInfluences.getIds().get(0));
590597

591598
sessionManager.onDirectInfluenceFromNotificationOpen(NOTIFICATION_ID);
599+
threadAndTaskWait();
592600

593601
iamInfluences = trackerFactory.getIAMChannelTracker().getCurrentSessionInfluence();
594602
notificationInfluences = trackerFactory.getNotificationChannelTracker().getCurrentSessionInfluence();

0 commit comments

Comments
 (0)