From 4be1b4d4913191e9d1833bd94184887ef2f526e2 Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Fri, 3 Apr 2020 09:19:05 -0700 Subject: [PATCH] Add support for AndroidX fragments (#957) Summary: Fix https://github.com/facebook/flipper/issues/931 This is not how I would *like* to fix this, but it should do the job. When the switch over to AndroidX was made, the overall abstraction started to leak and we really need to remodel this in its entirety. There's also the question of whether we want to support both support fragments and AndroidX fragments or not. Right now it's kinda-sorta supported but only under some circumstances, which is not great. I also added some more defensive try/catches as there's some unsafe casting involved and future changes may break this causing the entire layout to disappear. Change Log: Fix support for AndroidX fragments in Layout Inspector. Pull Request resolved: https://github.com/facebook/flipper/pull/957 Test Plan: Changed the sample app to include some AndroidX fragments and they now show up (again) in the view hierarchy: ![Screenshot 2020-04-01 13 40 53](https://user-images.githubusercontent.com/9906/78138910-915fbc00-741f-11ea-8386-4eeca9b7f932.png) Tested internally that FB4A fragments show up again, too: {F233098198} Reviewed By: mweststrate Differential Revision: D20792503 Pulled By: passy fbshipit-source-id: 7030b897ab547d1e8803b7f0d7aaa34263cfaed2 --- .../descriptors/ActivityDescriptor.java | 12 ++++++-- .../utils/stethocopies/FragmentCompat.java | 30 +++++++++++-------- .../stethocopies/FragmentCompatUtil.java | 12 +++++++- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/ActivityDescriptor.java b/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/ActivityDescriptor.java index 925a7a9a57f..8a4b1a9dc30 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/ActivityDescriptor.java +++ b/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/ActivityDescriptor.java @@ -8,6 +8,7 @@ package com.facebook.flipper.plugins.inspector.descriptors; import android.app.Activity; +import android.util.Log; import android.view.Window; import com.facebook.flipper.core.FlipperDynamic; import com.facebook.flipper.core.FlipperObject; @@ -25,6 +26,8 @@ public class ActivityDescriptor extends NodeDescriptor { + private static final String TAG = "ActivityDescriptor"; + @Override public void init(Activity node) {} @@ -112,9 +115,14 @@ private static List getDialogFragments(FragmentCompat compat, Activity a } FragmentManagerAccessor fragmentManagerAccessor = compat.forFragmentManager(); - List addedFragments = fragmentManagerAccessor.getAddedFragments(fragmentManager); + List addedFragments = null; + try { + addedFragments = fragmentManagerAccessor.getAddedFragments(fragmentManager); + } catch (Exception e) { + Log.e(TAG, "Failed to obtain list of fragments.", e); + } if (addedFragments == null) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } final List dialogFragments = new ArrayList<>(); diff --git a/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/stethocopies/FragmentCompat.java b/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/stethocopies/FragmentCompat.java index 61f26f4050c..d6e15b494d9 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/stethocopies/FragmentCompat.java +++ b/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/stethocopies/FragmentCompat.java @@ -9,7 +9,9 @@ import android.app.Activity; import android.os.Build; +import androidx.fragment.app.FragmentManager; import java.lang.reflect.Field; +import java.util.Collections; import java.util.List; import javax.annotation.Nullable; import javax.annotation.concurrent.NotThreadSafe; @@ -37,7 +39,7 @@ public abstract class FragmentCompat< static { sHasSupportFragment = - ReflectionUtil.tryGetClassForName("android.support.v4.app.Fragment") != null; + ReflectionUtil.tryGetClassForName("androidx.fragment.app.Fragment") != null; } @Nullable @@ -82,20 +84,22 @@ static class FragmentManagerAccessorViaReflection @Nullable @Override public List getAddedFragments(FRAGMENT_MANAGER fragmentManager) { - // This field is actually sitting on FragmentManagerImpl, which derives from FragmentManager. - if (mFieldMAdded == null) { - Field fieldMAdded = - ReflectionUtil.tryGetDeclaredField(fragmentManager.getClass(), "mAdded"); - - if (fieldMAdded != null) { - fieldMAdded.setAccessible(true); - mFieldMAdded = fieldMAdded; + if (fragmentManager instanceof android.app.FragmentManager) { + // This field is actually sitting on FragmentManagerImpl, which derives from + // FragmentManager. + if (mFieldMAdded == null) { + Field fieldMAdded = + ReflectionUtil.tryGetDeclaredField(fragmentManager.getClass(), "mAdded"); + + if (fieldMAdded != null) { + fieldMAdded.setAccessible(true); + mFieldMAdded = fieldMAdded; + } } + } else if (fragmentManager instanceof androidx.fragment.app.FragmentManager) { + return (List) ((FragmentManager) fragmentManager).getFragments(); } - - return (mFieldMAdded != null) - ? (List) ReflectionUtil.getFieldValue(mFieldMAdded, fragmentManager) - : null; + return Collections.emptyList(); } } } diff --git a/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/stethocopies/FragmentCompatUtil.java b/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/stethocopies/FragmentCompatUtil.java index 7049a5c06b1..b2fa3eee700 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/stethocopies/FragmentCompatUtil.java +++ b/android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/stethocopies/FragmentCompatUtil.java @@ -8,11 +8,15 @@ package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies; import android.app.Activity; +import android.util.Log; import android.view.View; +import java.util.Collections; import java.util.List; import javax.annotation.Nullable; public final class FragmentCompatUtil { + private static final String TAG = "FragmentCompatUtil"; + private FragmentCompatUtil() {} public static boolean isDialogFragment(Object fragment) { @@ -79,7 +83,13 @@ private static Object findFragmentForViewInActivity( @Nullable private static Object findFragmentForViewInFragmentManager( FragmentCompat compat, Object fragmentManager, View view) { - List fragments = compat.forFragmentManager().getAddedFragments(fragmentManager); + List fragments; + try { + fragments = compat.forFragmentManager().getAddedFragments(fragmentManager); + } catch (Exception e) { + fragments = Collections.emptyList(); + Log.e(TAG, "Failed to obtain list of fragments.", e); + } if (fragments != null) { for (int i = 0, N = fragments.size(); i < N; ++i) {