Skip to content

Commit 9218f96

Browse files
committed
Fix IAM redisplay when no dismiss
* If user navigates with backpress while an IAM is being display, IAM should continue displaying until user dismiss it. * Create new scenario for displaying IAM again when changing activity
1 parent f9cfa09 commit 9218f96

11 files changed

+255
-156
lines changed

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

Lines changed: 103 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import android.annotation.SuppressLint;
3131
import android.app.Activity;
32+
import android.content.Context;
3233
import android.content.pm.ActivityInfo;
3334
import android.content.res.Configuration;
3435
import android.os.Build;
@@ -42,95 +43,53 @@
4243
import java.util.Map;
4344
import java.util.concurrent.ConcurrentHashMap;
4445

45-
class ActivityLifecycleHandler {
46-
47-
static boolean nextResumeIsFirstActivity;
46+
class ActivityLifecycleHandler implements OSSystemConditionController.OSSystemConditionHandler {
4847

4948
abstract static class ActivityAvailableListener {
5049
void available(@NonNull Activity activity) {
5150
}
5251

53-
void stopped() {
52+
void stopped(@NonNull Activity activity) {
5453
}
5554

5655
void lostFocus() {
5756
}
5857
}
5958

60-
private static Map<String, ActivityAvailableListener> sActivityAvailableListeners = new ConcurrentHashMap<>();
61-
private static Map<String, OSSystemConditionController.OSSystemConditionObserver> sSystemConditionObservers = new ConcurrentHashMap<>();
62-
private static Map<String, KeyboardListener> sKeyboardListeners = new ConcurrentHashMap<>();
59+
private static final Object SYNC_LOCK = new Object();
60+
private static final String FOCUS_LOST_WORKER_TAG = "FOCUS_LOST_WORKER_TAG";
61+
private static final Map<String, ActivityAvailableListener> sActivityAvailableListeners = new ConcurrentHashMap<>();
62+
private static final Map<String, OSSystemConditionController.OSSystemConditionObserver> sSystemConditionObservers = new ConcurrentHashMap<>();
63+
private static final Map<String, KeyboardListener> sKeyboardListeners = new ConcurrentHashMap<>();
64+
6365
static FocusHandlerThread focusHandlerThread = new FocusHandlerThread();
6466
@SuppressLint("StaticFieldLeak")
65-
static Activity curActivity;
66-
67-
static void setSystemConditionObserver(String key, OSSystemConditionController.OSSystemConditionObserver systemConditionObserver) {
68-
if (curActivity != null) {
69-
ViewTreeObserver treeObserver = curActivity.getWindow().getDecorView().getViewTreeObserver();
70-
KeyboardListener keyboardListener = new KeyboardListener(systemConditionObserver, key);
71-
treeObserver.addOnGlobalLayoutListener(keyboardListener);
72-
sKeyboardListeners.put(key, keyboardListener);
73-
}
74-
sSystemConditionObservers.put(key, systemConditionObserver);
75-
}
67+
private Activity curActivity = null;
68+
private boolean nextResumeIsFirstActivity = false;
7669

77-
static void setActivityAvailableListener(String key, ActivityAvailableListener activityAvailableListener) {
78-
sActivityAvailableListeners.put(key, activityAvailableListener);
79-
if (curActivity != null)
80-
activityAvailableListener.available(curActivity);
81-
}
82-
83-
static void removeSystemConditionObserver(String key) {
84-
sKeyboardListeners.remove(key);
85-
sSystemConditionObservers.remove(key);
86-
}
87-
88-
static void removeActivityAvailableListener(String key) {
89-
sActivityAvailableListeners.remove(key);
90-
}
91-
92-
private static void setCurActivity(Activity activity) {
93-
curActivity = activity;
94-
for (Map.Entry<String, ActivityAvailableListener> entry : sActivityAvailableListeners.entrySet()) {
95-
entry.getValue().available(curActivity);
96-
}
97-
98-
try {
99-
ViewTreeObserver treeObserver = curActivity.getWindow().getDecorView().getViewTreeObserver();
100-
for (Map.Entry<String, OSSystemConditionController.OSSystemConditionObserver> entry : sSystemConditionObservers.entrySet()) {
101-
KeyboardListener keyboardListener = new KeyboardListener(entry.getValue(), entry.getKey());
102-
treeObserver.addOnGlobalLayoutListener(keyboardListener);
103-
sKeyboardListeners.put(entry.getKey(), keyboardListener);
104-
}
105-
} catch (RuntimeException e) {
106-
// Related to Unity Issue #239 on Github
107-
// https://github.com/OneSignal/OneSignal-Unity-SDK/issues/239
108-
// RuntimeException at ActivityLifecycleHandler.setCurActivity on Android (Unity 2.9.0)
109-
e.printStackTrace();
110-
}
111-
}
112-
113-
static void onConfigurationChanged(Configuration newConfig) {
70+
void onConfigurationChanged(Configuration newConfig, Activity activity) {
11471
// If Activity contains the configChanges orientation flag, re-create the view this way
11572
if (curActivity != null && OSUtils.hasConfigChangeFlag(curActivity, ActivityInfo.CONFIG_ORIENTATION)) {
116-
logOrientationChange(newConfig.orientation);
117-
onOrientationChanged();
73+
logOrientationChange(newConfig.orientation, activity);
74+
onOrientationChanged(activity);
11875
}
11976
}
12077

121-
static void onActivityCreated(Activity activity) {
78+
void onActivityCreated(Activity activity) {
12279
}
12380

124-
static void onActivityStarted(Activity activity) {
81+
void onActivityStarted(Activity activity) {
12582
}
12683

127-
static void onActivityResumed(Activity activity) {
84+
void onActivityResumed(Activity activity) {
85+
OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, "onActivityResumed: " + activity);
12886
setCurActivity(activity);
12987
logCurActivity();
13088
handleFocus();
13189
}
13290

133-
static void onActivityPaused(Activity activity) {
91+
void onActivityPaused(Activity activity) {
92+
OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, "onActivityPaused: " + activity);
13493
if (activity == curActivity) {
13594
curActivity = null;
13695
handleLostFocus();
@@ -139,7 +98,7 @@ static void onActivityPaused(Activity activity) {
13998
logCurActivity();
14099
}
141100

142-
static void onActivityStopped(Activity activity) {
101+
void onActivityStopped(Activity activity) {
143102
OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, "onActivityStopped: " + activity);
144103

145104
if (activity == curActivity) {
@@ -148,13 +107,13 @@ static void onActivityStopped(Activity activity) {
148107
}
149108

150109
for (Map.Entry<String, ActivityAvailableListener> entry : sActivityAvailableListeners.entrySet()) {
151-
entry.getValue().stopped();
110+
entry.getValue().stopped(activity);
152111
}
153112

154113
logCurActivity();
155114
}
156115

157-
static void onActivityDestroyed(Activity activity) {
116+
void onActivityDestroyed(Activity activity) {
158117
OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, "onActivityDestroyed: " + activity);
159118
sKeyboardListeners.clear();
160119

@@ -166,16 +125,16 @@ static void onActivityDestroyed(Activity activity) {
166125
logCurActivity();
167126
}
168127

169-
static private void logCurActivity() {
128+
private void logCurActivity() {
170129
OneSignal.Log(OneSignal.LOG_LEVEL.DEBUG, "curActivity is NOW: " + (curActivity != null ? "" + curActivity.getClass().getName() + ":" + curActivity : "null"));
171130
}
172131

173-
private static void logOrientationChange(int orientation) {
132+
private void logOrientationChange(int orientation, Activity activity) {
174133
// Log device orientation change
175134
if (orientation == Configuration.ORIENTATION_LANDSCAPE)
176-
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "Configuration Orientation Change: LANDSCAPE (" + orientation + ")");
135+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "Configuration Orientation Change: LANDSCAPE (" + orientation + ") on activity: " + activity);
177136
else if (orientation == Configuration.ORIENTATION_PORTRAIT)
178-
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "Configuration Orientation Change: PORTRAIT (" + orientation + ")");
137+
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "Configuration Orientation Change: PORTRAIT (" + orientation + ") on activity: " + activity);
179138
}
180139

181140
/**
@@ -184,11 +143,11 @@ else if (orientation == Configuration.ORIENTATION_PORTRAIT)
184143
* This fix was originally implemented for In App Messages not being re-shown when orientation
185144
* was changed on wrapper SDK apps
186145
*/
187-
private static void onOrientationChanged() {
146+
private void onOrientationChanged(Activity activity) {
188147
// Remove view
189148
handleLostFocus();
190149
for (Map.Entry<String, ActivityAvailableListener> entry : sActivityAvailableListeners.entrySet()) {
191-
entry.getValue().stopped();
150+
entry.getValue().stopped(activity);
192151
}
193152

194153
// Show view
@@ -198,20 +157,83 @@ private static void onOrientationChanged() {
198157

199158
ViewTreeObserver treeObserver = curActivity.getWindow().getDecorView().getViewTreeObserver();
200159
for (Map.Entry<String, OSSystemConditionController.OSSystemConditionObserver> entry : sSystemConditionObservers.entrySet()) {
201-
KeyboardListener keyboardListener = new KeyboardListener(entry.getValue(), entry.getKey());
160+
KeyboardListener keyboardListener = new KeyboardListener(this, entry.getValue(), entry.getKey());
202161
treeObserver.addOnGlobalLayoutListener(keyboardListener);
203162
sKeyboardListeners.put(entry.getKey(), keyboardListener);
204163
}
205164
handleFocus();
206165
}
207166

208-
static private void handleLostFocus() {
167+
void addSystemConditionObserver(String key, OSSystemConditionController.OSSystemConditionObserver systemConditionObserver) {
168+
if (curActivity != null) {
169+
ViewTreeObserver treeObserver = curActivity.getWindow().getDecorView().getViewTreeObserver();
170+
KeyboardListener keyboardListener = new KeyboardListener(this, systemConditionObserver, key);
171+
treeObserver.addOnGlobalLayoutListener(keyboardListener);
172+
sKeyboardListeners.put(key, keyboardListener);
173+
}
174+
sSystemConditionObservers.put(key, systemConditionObserver);
175+
}
176+
177+
public void removeSystemConditionObserver(@NonNull String key, @NonNull KeyboardListener keyboardListener) {
178+
if (curActivity != null) {
179+
ViewTreeObserver treeObserver = curActivity.getWindow().getDecorView().getViewTreeObserver();
180+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
181+
treeObserver.removeGlobalOnLayoutListener(keyboardListener);
182+
} else {
183+
treeObserver.removeOnGlobalLayoutListener(keyboardListener);
184+
}
185+
}
186+
187+
sKeyboardListeners.remove(key);
188+
sSystemConditionObservers.remove(key);
189+
}
190+
191+
void addActivityAvailableListener(String key, ActivityAvailableListener activityAvailableListener) {
192+
sActivityAvailableListeners.put(key, activityAvailableListener);
193+
if (curActivity != null)
194+
activityAvailableListener.available(curActivity);
195+
}
196+
197+
void removeActivityAvailableListener(String key) {
198+
sActivityAvailableListeners.remove(key);
199+
}
200+
201+
public Activity getCurActivity() {
202+
return curActivity;
203+
}
204+
205+
public void setCurActivity(Activity activity) {
206+
curActivity = activity;
207+
for (Map.Entry<String, ActivityAvailableListener> entry : sActivityAvailableListeners.entrySet()) {
208+
entry.getValue().available(curActivity);
209+
}
210+
211+
try {
212+
ViewTreeObserver treeObserver = curActivity.getWindow().getDecorView().getViewTreeObserver();
213+
for (Map.Entry<String, OSSystemConditionController.OSSystemConditionObserver> entry : sSystemConditionObservers.entrySet()) {
214+
KeyboardListener keyboardListener = new KeyboardListener(this, entry.getValue(), entry.getKey());
215+
treeObserver.addOnGlobalLayoutListener(keyboardListener);
216+
sKeyboardListeners.put(entry.getKey(), keyboardListener);
217+
}
218+
} catch (RuntimeException e) {
219+
// Related to Unity Issue #239 on Github
220+
// https://github.com/OneSignal/OneSignal-Unity-SDK/issues/239
221+
// RuntimeException at ActivityLifecycleHandler.setCurActivity on Android (Unity 2.9.0)
222+
e.printStackTrace();
223+
}
224+
}
225+
226+
void setNextResumeIsFirstActivity(boolean nextResumeIsFirstActivity) {
227+
this.nextResumeIsFirstActivity = nextResumeIsFirstActivity;
228+
}
229+
230+
private void handleLostFocus() {
209231
focusHandlerThread.runRunnable(new AppFocusRunnable());
210232
}
211233

212-
static private void handleFocus() {
234+
private void handleFocus() {
213235
if (focusHandlerThread.hasBackgrounded() || nextResumeIsFirstActivity) {
214-
nextResumeIsFirstActivity = false;
236+
setNextResumeIsFirstActivity(false);
215237
focusHandlerThread.resetBackgroundState();
216238
OneSignal.onAppFocus();
217239
} else
@@ -259,7 +281,7 @@ private static class AppFocusRunnable implements Runnable {
259281
private boolean backgrounded, completed;
260282

261283
public void run() {
262-
if (curActivity != null)
284+
if (OneSignal.getCurrentActivity() != null)
263285
return;
264286

265287
backgrounded = true;
@@ -271,29 +293,23 @@ public void run() {
271293
}
272294
}
273295

274-
private static class KeyboardListener implements ViewTreeObserver.OnGlobalLayoutListener {
296+
static class KeyboardListener implements ViewTreeObserver.OnGlobalLayoutListener {
275297

276298
private final OSSystemConditionController.OSSystemConditionObserver observer;
299+
private final OSSystemConditionController.OSSystemConditionHandler systemConditionListener;
277300
private final String key;
278301

279-
private KeyboardListener(OSSystemConditionController.OSSystemConditionObserver observer, String key) {
302+
private KeyboardListener(OSSystemConditionController.OSSystemConditionHandler systemConditionListener, OSSystemConditionController.OSSystemConditionObserver observer, String key) {
303+
this.systemConditionListener = systemConditionListener;
280304
this.observer = observer;
281305
this.key = key;
282306
}
283307

284308
@Override
285309
public void onGlobalLayout() {
286-
boolean keyboardUp = OSViewUtils.isKeyboardUp(new WeakReference<>(ActivityLifecycleHandler.curActivity));
310+
boolean keyboardUp = OSViewUtils.isKeyboardUp(new WeakReference<>(OneSignal.getCurrentActivity()));
287311
if (!keyboardUp) {
288-
if (curActivity != null) {
289-
ViewTreeObserver treeObserver = curActivity.getWindow().getDecorView().getViewTreeObserver();
290-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
291-
treeObserver.removeGlobalOnLayoutListener(KeyboardListener.this);
292-
} else {
293-
treeObserver.removeOnGlobalLayoutListener(KeyboardListener.this);
294-
}
295-
}
296-
ActivityLifecycleHandler.removeSystemConditionObserver(key);
312+
systemConditionListener.removeSystemConditionObserver(key, this);
297313
observer.systemConditionChanged();
298314
}
299315
}

0 commit comments

Comments
 (0)