11package com .blankj .utilcode .util ;
22
33import android .animation .ValueAnimator ;
4- import android .annotation .SuppressLint ;
54import android .app .Activity ;
65import android .app .Application ;
76import android .arch .lifecycle .Lifecycle ;
@@ -35,7 +34,7 @@ final class UtilsActivityLifecycleImpl implements Application.ActivityLifecycleC
3534
3635 static final UtilsActivityLifecycleImpl INSTANCE = new UtilsActivityLifecycleImpl ();
3736
38- final LinkedList <Activity > mActivityList = new LinkedList <>();
37+ private final LinkedList <Activity > mActivityList = new LinkedList <>();
3938
4039 private final List <Utils .OnAppStatusChangedListener > mStatusListeners = new ArrayList <>();
4140 private final Map <Activity , List <Utils .OnActivityDestroyedListener >> mDestroyedListenerMap = new HashMap <>();
@@ -51,20 +50,23 @@ void init() {
5150 }
5251
5352 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 ;
6157 }
58+ return activity ;
6259 }
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 ;
6666 }
67- return topActivityByReflect ;
67+ List <Activity > reflectActivities = getActivitiesByReflect ();
68+ mActivityList .addAll (reflectActivities );
69+ return mActivityList ;
6870 }
6971
7072 void addOnAppStatusChangedListener (final Utils .OnAppStatusChangedListener listener ) {
@@ -240,12 +242,12 @@ private void postStatus(final Activity activity, final boolean isForeground) {
240242
241243 private void setTopActivity (final Activity activity ) {
242244 if (mActivityList .contains (activity )) {
243- if (!mActivityList .getLast ().equals (activity )) {
245+ if (!mActivityList .getFirst ().equals (activity )) {
244246 mActivityList .remove (activity );
245- mActivityList .addLast (activity );
247+ mActivityList .addFirst (activity );
246248 }
247249 } else {
248- mActivityList .addLast (activity );
250+ mActivityList .addFirst (activity );
249251 }
250252 }
251253
@@ -292,29 +294,86 @@ private void consumeActivityLifecycleCallbacks(Activity activity, Lifecycle.Even
292294 }
293295 }
294296
295- private Activity getTopActivityByReflect () {
297+ private List <Activity > getActivitiesByReflect () {
298+ LinkedList <Activity > list = new LinkedList <>();
299+ Activity topActivity = null ;
296300 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 );
312324 }
313325 }
314326 } 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 ;
316376 }
317- return null ;
318377 }
319378
320379 /**
0 commit comments