29
29
30
30
import android .annotation .SuppressLint ;
31
31
import android .app .Activity ;
32
+ import android .content .Context ;
32
33
import android .content .pm .ActivityInfo ;
33
34
import android .content .res .Configuration ;
34
35
import android .os .Build ;
42
43
import java .util .Map ;
43
44
import java .util .concurrent .ConcurrentHashMap ;
44
45
45
- class ActivityLifecycleHandler {
46
-
47
- static boolean nextResumeIsFirstActivity ;
46
+ class ActivityLifecycleHandler implements OSSystemConditionController .OSSystemConditionHandler {
48
47
49
48
abstract static class ActivityAvailableListener {
50
49
void available (@ NonNull Activity activity ) {
51
50
}
52
51
53
- void stopped () {
52
+ void stopped (@ NonNull Activity activity ) {
54
53
}
55
54
56
55
void lostFocus () {
57
56
}
58
57
}
59
58
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
+
63
65
static FocusHandlerThread focusHandlerThread = new FocusHandlerThread ();
64
66
@ 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 ;
76
69
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 ) {
114
71
// If Activity contains the configChanges orientation flag, re-create the view this way
115
72
if (curActivity != null && OSUtils .hasConfigChangeFlag (curActivity , ActivityInfo .CONFIG_ORIENTATION )) {
116
- logOrientationChange (newConfig .orientation );
117
- onOrientationChanged ();
73
+ logOrientationChange (newConfig .orientation , activity );
74
+ onOrientationChanged (activity );
118
75
}
119
76
}
120
77
121
- static void onActivityCreated (Activity activity ) {
78
+ void onActivityCreated (Activity activity ) {
122
79
}
123
80
124
- static void onActivityStarted (Activity activity ) {
81
+ void onActivityStarted (Activity activity ) {
125
82
}
126
83
127
- static void onActivityResumed (Activity activity ) {
84
+ void onActivityResumed (Activity activity ) {
85
+ OneSignal .Log (OneSignal .LOG_LEVEL .DEBUG , "onActivityResumed: " + activity );
128
86
setCurActivity (activity );
129
87
logCurActivity ();
130
88
handleFocus ();
131
89
}
132
90
133
- static void onActivityPaused (Activity activity ) {
91
+ void onActivityPaused (Activity activity ) {
92
+ OneSignal .Log (OneSignal .LOG_LEVEL .DEBUG , "onActivityPaused: " + activity );
134
93
if (activity == curActivity ) {
135
94
curActivity = null ;
136
95
handleLostFocus ();
@@ -139,7 +98,7 @@ static void onActivityPaused(Activity activity) {
139
98
logCurActivity ();
140
99
}
141
100
142
- static void onActivityStopped (Activity activity ) {
101
+ void onActivityStopped (Activity activity ) {
143
102
OneSignal .Log (OneSignal .LOG_LEVEL .DEBUG , "onActivityStopped: " + activity );
144
103
145
104
if (activity == curActivity ) {
@@ -148,13 +107,13 @@ static void onActivityStopped(Activity activity) {
148
107
}
149
108
150
109
for (Map .Entry <String , ActivityAvailableListener > entry : sActivityAvailableListeners .entrySet ()) {
151
- entry .getValue ().stopped ();
110
+ entry .getValue ().stopped (activity );
152
111
}
153
112
154
113
logCurActivity ();
155
114
}
156
115
157
- static void onActivityDestroyed (Activity activity ) {
116
+ void onActivityDestroyed (Activity activity ) {
158
117
OneSignal .Log (OneSignal .LOG_LEVEL .DEBUG , "onActivityDestroyed: " + activity );
159
118
sKeyboardListeners .clear ();
160
119
@@ -166,16 +125,16 @@ static void onActivityDestroyed(Activity activity) {
166
125
logCurActivity ();
167
126
}
168
127
169
- static private void logCurActivity () {
128
+ private void logCurActivity () {
170
129
OneSignal .Log (OneSignal .LOG_LEVEL .DEBUG , "curActivity is NOW: " + (curActivity != null ? "" + curActivity .getClass ().getName () + ":" + curActivity : "null" ));
171
130
}
172
131
173
- private static void logOrientationChange (int orientation ) {
132
+ private void logOrientationChange (int orientation , Activity activity ) {
174
133
// Log device orientation change
175
134
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 );
177
136
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 );
179
138
}
180
139
181
140
/**
@@ -184,11 +143,11 @@ else if (orientation == Configuration.ORIENTATION_PORTRAIT)
184
143
* This fix was originally implemented for In App Messages not being re-shown when orientation
185
144
* was changed on wrapper SDK apps
186
145
*/
187
- private static void onOrientationChanged () {
146
+ private void onOrientationChanged (Activity activity ) {
188
147
// Remove view
189
148
handleLostFocus ();
190
149
for (Map .Entry <String , ActivityAvailableListener > entry : sActivityAvailableListeners .entrySet ()) {
191
- entry .getValue ().stopped ();
150
+ entry .getValue ().stopped (activity );
192
151
}
193
152
194
153
// Show view
@@ -198,20 +157,83 @@ private static void onOrientationChanged() {
198
157
199
158
ViewTreeObserver treeObserver = curActivity .getWindow ().getDecorView ().getViewTreeObserver ();
200
159
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 ());
202
161
treeObserver .addOnGlobalLayoutListener (keyboardListener );
203
162
sKeyboardListeners .put (entry .getKey (), keyboardListener );
204
163
}
205
164
handleFocus ();
206
165
}
207
166
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 () {
209
231
focusHandlerThread .runRunnable (new AppFocusRunnable ());
210
232
}
211
233
212
- static private void handleFocus () {
234
+ private void handleFocus () {
213
235
if (focusHandlerThread .hasBackgrounded () || nextResumeIsFirstActivity ) {
214
- nextResumeIsFirstActivity = false ;
236
+ setNextResumeIsFirstActivity ( false ) ;
215
237
focusHandlerThread .resetBackgroundState ();
216
238
OneSignal .onAppFocus ();
217
239
} else
@@ -259,7 +281,7 @@ private static class AppFocusRunnable implements Runnable {
259
281
private boolean backgrounded , completed ;
260
282
261
283
public void run () {
262
- if (curActivity != null )
284
+ if (OneSignal . getCurrentActivity () != null )
263
285
return ;
264
286
265
287
backgrounded = true ;
@@ -271,29 +293,23 @@ public void run() {
271
293
}
272
294
}
273
295
274
- private static class KeyboardListener implements ViewTreeObserver .OnGlobalLayoutListener {
296
+ static class KeyboardListener implements ViewTreeObserver .OnGlobalLayoutListener {
275
297
276
298
private final OSSystemConditionController .OSSystemConditionObserver observer ;
299
+ private final OSSystemConditionController .OSSystemConditionHandler systemConditionListener ;
277
300
private final String key ;
278
301
279
- private KeyboardListener (OSSystemConditionController .OSSystemConditionObserver observer , String key ) {
302
+ private KeyboardListener (OSSystemConditionController .OSSystemConditionHandler systemConditionListener , OSSystemConditionController .OSSystemConditionObserver observer , String key ) {
303
+ this .systemConditionListener = systemConditionListener ;
280
304
this .observer = observer ;
281
305
this .key = key ;
282
306
}
283
307
284
308
@ Override
285
309
public void onGlobalLayout () {
286
- boolean keyboardUp = OSViewUtils .isKeyboardUp (new WeakReference <>(ActivityLifecycleHandler . curActivity ));
310
+ boolean keyboardUp = OSViewUtils .isKeyboardUp (new WeakReference <>(OneSignal . getCurrentActivity () ));
287
311
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 );
297
313
observer .systemConditionChanged ();
298
314
}
299
315
}
0 commit comments