1
1
package com .blankj .utilcode .util ;
2
2
3
3
import android .animation .ValueAnimator ;
4
- import android .annotation .SuppressLint ;
5
4
import android .app .Activity ;
6
5
import android .app .Application ;
7
6
import android .arch .lifecycle .Lifecycle ;
@@ -35,7 +34,7 @@ final class UtilsActivityLifecycleImpl implements Application.ActivityLifecycleC
35
34
36
35
static final UtilsActivityLifecycleImpl INSTANCE = new UtilsActivityLifecycleImpl ();
37
36
38
- final LinkedList <Activity > mActivityList = new LinkedList <>();
37
+ private final LinkedList <Activity > mActivityList = new LinkedList <>();
39
38
40
39
private final List <Utils .OnAppStatusChangedListener > mStatusListeners = new ArrayList <>();
41
40
private final Map <Activity , List <Utils .OnActivityDestroyedListener >> mDestroyedListenerMap = new HashMap <>();
@@ -51,20 +50,23 @@ void init() {
51
50
}
52
51
53
52
Activity getTopActivity () {
54
- if (!mActivityList .isEmpty ()) {
55
- for (int i = mActivityList .size () - 1 ; i >= 0 ; i --) {
56
- Activity activity = mActivityList .get (i );
57
- if (!UtilsBridge .isActivityAlive (activity )) {
58
- continue ;
59
- }
60
- return activity ;
53
+ List <Activity > activityList = getActivityList ();
54
+ for (Activity activity : activityList ) {
55
+ if (!UtilsBridge .isActivityAlive (activity )) {
56
+ continue ;
61
57
}
58
+ return activity ;
62
59
}
63
- Activity topActivityByReflect = getTopActivityByReflect ();
64
- if (topActivityByReflect != null ) {
65
- setTopActivity (topActivityByReflect );
60
+ return null ;
61
+ }
62
+
63
+ List <Activity > getActivityList () {
64
+ if (!mActivityList .isEmpty ()) {
65
+ return mActivityList ;
66
66
}
67
- return topActivityByReflect ;
67
+ List <Activity > reflectActivities = getActivitiesByReflect ();
68
+ mActivityList .addAll (reflectActivities );
69
+ return mActivityList ;
68
70
}
69
71
70
72
void addOnAppStatusChangedListener (final Utils .OnAppStatusChangedListener listener ) {
@@ -240,12 +242,12 @@ private void postStatus(final Activity activity, final boolean isForeground) {
240
242
241
243
private void setTopActivity (final Activity activity ) {
242
244
if (mActivityList .contains (activity )) {
243
- if (!mActivityList .getLast ().equals (activity )) {
245
+ if (!mActivityList .getFirst ().equals (activity )) {
244
246
mActivityList .remove (activity );
245
- mActivityList .addLast (activity );
247
+ mActivityList .addFirst (activity );
246
248
}
247
249
} else {
248
- mActivityList .addLast (activity );
250
+ mActivityList .addFirst (activity );
249
251
}
250
252
}
251
253
@@ -292,29 +294,86 @@ private void consumeActivityLifecycleCallbacks(Activity activity, Lifecycle.Even
292
294
}
293
295
}
294
296
295
- private Activity getTopActivityByReflect () {
297
+ private List <Activity > getActivitiesByReflect () {
298
+ LinkedList <Activity > list = new LinkedList <>();
299
+ Activity topActivity = null ;
296
300
try {
297
- @ SuppressLint ("PrivateApi" )
298
- Class <?> activityThreadClass = Class .forName ("android.app.ActivityThread" );
299
- Object currentActivityThreadMethod = activityThreadClass .getMethod ("currentActivityThread" ).invoke (null );
300
- Field mActivityListField = activityThreadClass .getDeclaredField ("mActivityList" );
301
- mActivityListField .setAccessible (true );
302
- Map activities = (Map ) mActivityListField .get (currentActivityThreadMethod );
303
- if (activities == null ) return null ;
304
- for (Object activityRecord : activities .values ()) {
305
- Class activityRecordClass = activityRecord .getClass ();
306
- Field pausedField = activityRecordClass .getDeclaredField ("paused" );
307
- pausedField .setAccessible (true );
308
- if (!pausedField .getBoolean (activityRecord )) {
309
- Field activityField = activityRecordClass .getDeclaredField ("activity" );
310
- activityField .setAccessible (true );
311
- return (Activity ) activityField .get (activityRecord );
301
+ Object activityThread = getActivityThread ();
302
+ Field mActivitiesField = activityThread .getClass ().getDeclaredField ("mActivities" );
303
+ mActivitiesField .setAccessible (true );
304
+ Object mActivities = mActivitiesField .get (activityThread );
305
+ if (!(mActivities instanceof Map )) {
306
+ return list ;
307
+ }
308
+ Map <Object , Object > binder_activityClientRecord_map = (Map <Object , Object >) mActivities ;
309
+ for (Object activityRecord : binder_activityClientRecord_map .values ()) {
310
+ Class activityClientRecordClass = activityRecord .getClass ();
311
+ Field activityField = activityClientRecordClass .getDeclaredField ("activity" );
312
+ activityField .setAccessible (true );
313
+ Activity activity = (Activity ) activityField .get (activityRecord );
314
+ if (topActivity == null ) {
315
+ Field pausedField = activityClientRecordClass .getDeclaredField ("paused" );
316
+ pausedField .setAccessible (true );
317
+ if (!pausedField .getBoolean (activityRecord )) {
318
+ topActivity = activity ;
319
+ } else {
320
+ list .add (activity );
321
+ }
322
+ } else {
323
+ list .add (activity );
312
324
}
313
325
}
314
326
} catch (Exception e ) {
315
- Log .e ("UtilsActivityLifecycle" , e .getMessage ());
327
+ Log .e ("UtilsActivityLifecycle" , "getActivitiesByReflect: " + e .getMessage ());
328
+ }
329
+ if (topActivity != null ) {
330
+ list .addFirst (topActivity );
331
+ }
332
+ return list ;
333
+ }
334
+
335
+ private Object getActivityThread () {
336
+ Object activityThread = getActivityThreadInActivityThreadStaticField ();
337
+ if (activityThread != null ) return activityThread ;
338
+ activityThread = getActivityThreadInActivityThreadStaticMethod ();
339
+ if (activityThread != null ) return activityThread ;
340
+ return getActivityThreadInLoadedApkField ();
341
+ }
342
+
343
+ private Object getActivityThreadInActivityThreadStaticField () {
344
+ try {
345
+ Class activityThreadClass = Class .forName ("android.app.ActivityThread" );
346
+ Field sCurrentActivityThreadField = activityThreadClass .getDeclaredField ("sCurrentActivityThread" );
347
+ sCurrentActivityThreadField .setAccessible (true );
348
+ return sCurrentActivityThreadField .get (null );
349
+ } catch (Exception e ) {
350
+ Log .e ("UtilsActivityLifecycle" , "getActivityThreadInActivityThreadStaticField: " + e .getMessage ());
351
+ return null ;
352
+ }
353
+ }
354
+
355
+ private Object getActivityThreadInActivityThreadStaticMethod () {
356
+ try {
357
+ Class activityThreadClass = Class .forName ("android.app.ActivityThread" );
358
+ return activityThreadClass .getMethod ("currentActivityThread" ).invoke (null );
359
+ } catch (Exception e ) {
360
+ Log .e ("UtilsActivityLifecycle" , "getActivityThreadInActivityThreadStaticMethod: " + e .getMessage ());
361
+ return null ;
362
+ }
363
+ }
364
+
365
+ private Object getActivityThreadInLoadedApkField () {
366
+ try {
367
+ Field mLoadedApkField = Application .class .getDeclaredField ("mLoadedApk" );
368
+ mLoadedApkField .setAccessible (true );
369
+ Object mLoadedApk = mLoadedApkField .get (Utils .getApp ());
370
+ Field mActivityThreadField = mLoadedApk .getClass ().getDeclaredField ("mActivityThread" );
371
+ mActivityThreadField .setAccessible (true );
372
+ return mActivityThreadField .get (mLoadedApk );
373
+ } catch (Exception e ) {
374
+ Log .e ("UtilsActivityLifecycle" , "getActivityThreadInLoadedApkField: " + e .getMessage ());
375
+ return null ;
316
376
}
317
- return null ;
318
377
}
319
378
320
379
/**
0 commit comments