Remove stetho (#762)
Summary: ## Summary Resolves https://github.com/facebook/flipper/issues/607 This removes stetho dependencies directly in favor of just copying in the used classes. This removes the last non-androidx dependency from the project, and is useful as stetho appears to be unmaintained. The fresco stetho dependency appeared to be completely unused. ## Changelog Remove stetho dependencies. It was unused other than a few utility methods, but came at the cost of preventing Flipper consumers from completely removing dependencies that hadn't updated to Androidx yet. Pull Request resolved: https://github.com/facebook/flipper/pull/762 Test Plan: Existing tests still pass with no regressions. Functionally this should be no difference. Reviewed By: jknoxville Differential Revision: D19577969 Pulled By: passy fbshipit-source-id: b277ddf97a9d2c846dd0b9227c02bb46c1ecd930
This commit is contained in:
committed by
Facebook Github Bot
parent
bdd4516dc4
commit
48d6ea4c30
@@ -63,7 +63,6 @@ android {
|
|||||||
implementation deps.soloader
|
implementation deps.soloader
|
||||||
implementation deps.jsr305
|
implementation deps.jsr305
|
||||||
implementation deps.supportAppCompat
|
implementation deps.supportAppCompat
|
||||||
implementation deps.stetho
|
|
||||||
|
|
||||||
testImplementation deps.mockito
|
testImplementation deps.mockito
|
||||||
testImplementation deps.robolectric
|
testImplementation deps.robolectric
|
||||||
|
|||||||
@@ -21,8 +21,12 @@ android {
|
|||||||
implementation project(':android')
|
implementation project(':android')
|
||||||
implementation deps.fresco
|
implementation deps.fresco
|
||||||
implementation deps.frescoFlipper
|
implementation deps.frescoFlipper
|
||||||
implementation deps.frescoStetho
|
|
||||||
compileOnly deps.jsr305
|
compileOnly deps.jsr305
|
||||||
|
|
||||||
|
// Exclude the actual stetho dep as we only want some of the fresco APIs here
|
||||||
|
implementation(deps.frescoStetho) {
|
||||||
|
exclude group: 'com.facebook.stetho'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import com.facebook.flipper.core.FlipperObject;
|
|||||||
import com.facebook.flipper.plugins.inspector.Named;
|
import com.facebook.flipper.plugins.inspector.Named;
|
||||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||||
import com.facebook.flipper.plugins.inspector.Touch;
|
import com.facebook.flipper.plugins.inspector.Touch;
|
||||||
import com.facebook.stetho.common.android.FragmentActivityAccessor;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentActivityAccessor;
|
||||||
import com.facebook.stetho.common.android.FragmentCompat;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentCompat;
|
||||||
import com.facebook.stetho.common.android.FragmentManagerAccessor;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentManagerAccessor;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import com.facebook.flipper.core.FlipperObject;
|
|||||||
import com.facebook.flipper.plugins.inspector.Named;
|
import com.facebook.flipper.plugins.inspector.Named;
|
||||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||||
import com.facebook.flipper.plugins.inspector.Touch;
|
import com.facebook.flipper.plugins.inspector.Touch;
|
||||||
import com.facebook.stetho.common.android.ResourcesUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.ResourcesUtil;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import com.facebook.flipper.core.FlipperObject;
|
|||||||
import com.facebook.flipper.plugins.inspector.Named;
|
import com.facebook.flipper.plugins.inspector.Named;
|
||||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||||
import com.facebook.flipper.plugins.inspector.Touch;
|
import com.facebook.flipper.plugins.inspector.Touch;
|
||||||
import com.facebook.stetho.common.android.ResourcesUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.ResourcesUtil;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityEva
|
|||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityRoleUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityRoleUtil;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityUtil;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.EnumMapping;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.EnumMapping;
|
||||||
import com.facebook.stetho.common.android.ResourcesUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.ResourcesUtil;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import com.facebook.flipper.plugins.inspector.InspectorValue;
|
|||||||
import com.facebook.flipper.plugins.inspector.Named;
|
import com.facebook.flipper.plugins.inspector.Named;
|
||||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||||
import com.facebook.flipper.plugins.inspector.Touch;
|
import com.facebook.flipper.plugins.inspector.Touch;
|
||||||
import com.facebook.stetho.common.android.FragmentCompatUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentCompatUtil;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
|
||||||
|
public interface DialogFragmentAccessor<DIALOG_FRAGMENT, FRAGMENT, FRAGMENT_MANAGER>
|
||||||
|
extends FragmentAccessor<FRAGMENT, FRAGMENT_MANAGER> {
|
||||||
|
Dialog getDialog(DIALOG_FRAGMENT dialogFragment);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.view.View;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface FragmentAccessor<FRAGMENT, FRAGMENT_MANAGER> {
|
||||||
|
int NO_ID = 0;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
FRAGMENT_MANAGER getFragmentManager(FRAGMENT fragment);
|
||||||
|
|
||||||
|
Resources getResources(FRAGMENT fragment);
|
||||||
|
|
||||||
|
int getId(FRAGMENT fragment);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String getTag(FRAGMENT fragment);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
View getView(FRAGMENT fragment);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
FRAGMENT_MANAGER getChildFragmentManager(FRAGMENT fragment);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface FragmentActivityAccessor<FRAGMENT_ACTIVITY extends Activity, FRAGMENT_MANAGER> {
|
||||||
|
@Nullable
|
||||||
|
FRAGMENT_MANAGER getFragmentManager(FRAGMENT_ACTIVITY activity);
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Build;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compatibility abstraction which allows us to generalize access to both the support library's
|
||||||
|
* fragments and the built-in framework version. Note: both versions can be live at the same time in
|
||||||
|
* a single application and even on a single object instance.
|
||||||
|
*
|
||||||
|
* <p>Type safety is enforced via generics internal to the implementation but treated as opaque from
|
||||||
|
* the outside.
|
||||||
|
*
|
||||||
|
* @param <FRAGMENT>
|
||||||
|
* @param <DIALOG_FRAGMENT>
|
||||||
|
* @param <FRAGMENT_MANAGER>
|
||||||
|
* @param <FRAGMENT_ACTIVITY>
|
||||||
|
*/
|
||||||
|
@NotThreadSafe
|
||||||
|
public abstract class FragmentCompat<
|
||||||
|
FRAGMENT, DIALOG_FRAGMENT, FRAGMENT_MANAGER, FRAGMENT_ACTIVITY extends Activity> {
|
||||||
|
private static FragmentCompat sFrameworkInstance;
|
||||||
|
private static FragmentCompat sSupportInstance;
|
||||||
|
|
||||||
|
private static final boolean sHasSupportFragment;
|
||||||
|
|
||||||
|
static {
|
||||||
|
sHasSupportFragment =
|
||||||
|
ReflectionUtil.tryGetClassForName("android.support.v4.app.Fragment") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static FragmentCompat getFrameworkInstance() {
|
||||||
|
if (sFrameworkInstance == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||||
|
sFrameworkInstance = new FragmentCompatFramework();
|
||||||
|
}
|
||||||
|
return sFrameworkInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static FragmentCompat getSupportLibInstance() {
|
||||||
|
if (sSupportInstance == null && sHasSupportFragment) {
|
||||||
|
sSupportInstance = new FragmentCompatSupportLib();
|
||||||
|
}
|
||||||
|
return sSupportInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
FragmentCompat() {}
|
||||||
|
|
||||||
|
public abstract Class<FRAGMENT> getFragmentClass();
|
||||||
|
|
||||||
|
public abstract Class<DIALOG_FRAGMENT> getDialogFragmentClass();
|
||||||
|
|
||||||
|
public abstract Class<FRAGMENT_ACTIVITY> getFragmentActivityClass();
|
||||||
|
|
||||||
|
public abstract FragmentAccessor<FRAGMENT, FRAGMENT_MANAGER> forFragment();
|
||||||
|
|
||||||
|
public abstract DialogFragmentAccessor<DIALOG_FRAGMENT, FRAGMENT, FRAGMENT_MANAGER>
|
||||||
|
forDialogFragment();
|
||||||
|
|
||||||
|
public abstract FragmentManagerAccessor<FRAGMENT_MANAGER, FRAGMENT> forFragmentManager();
|
||||||
|
|
||||||
|
public abstract FragmentActivityAccessor<FRAGMENT_ACTIVITY, FRAGMENT_MANAGER>
|
||||||
|
forFragmentActivity();
|
||||||
|
|
||||||
|
static class FragmentManagerAccessorViaReflection<FRAGMENT_MANAGER, FRAGMENT>
|
||||||
|
implements FragmentManagerAccessor<FRAGMENT_MANAGER, FRAGMENT> {
|
||||||
|
@Nullable private Field mFieldMAdded;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public List<FRAGMENT> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (mFieldMAdded != null)
|
||||||
|
? (List<FRAGMENT>) ReflectionUtil.getFieldValue(mFieldMAdded, fragmentManager)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.DialogFragment;
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.app.FragmentManager;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.View;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||||
|
final class FragmentCompatFramework
|
||||||
|
extends FragmentCompat<Fragment, DialogFragment, FragmentManager, Activity> {
|
||||||
|
private static final FragmentAccessorFrameworkHoneycomb sFragmentAccessor;
|
||||||
|
private static final DialogFragmentAccessorFramework sDialogFragmentAccessor;
|
||||||
|
private static final FragmentManagerAccessorViaReflection<FragmentManager, Fragment>
|
||||||
|
sFragmentManagerAccessor = new FragmentManagerAccessorViaReflection<>();
|
||||||
|
private static final FragmentActivityAccessorFramework sFragmentActivityAccessor =
|
||||||
|
new FragmentActivityAccessorFramework();
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||||
|
sFragmentAccessor = new FragmentAccessorFrameworkJellyBean();
|
||||||
|
} else {
|
||||||
|
sFragmentAccessor = new FragmentAccessorFrameworkHoneycomb();
|
||||||
|
}
|
||||||
|
|
||||||
|
sDialogFragmentAccessor = new DialogFragmentAccessorFramework(sFragmentAccessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Fragment> getFragmentClass() {
|
||||||
|
return Fragment.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<DialogFragment> getDialogFragmentClass() {
|
||||||
|
return DialogFragment.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Activity> getFragmentActivityClass() {
|
||||||
|
return Activity.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FragmentAccessorFrameworkHoneycomb forFragment() {
|
||||||
|
return sFragmentAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DialogFragmentAccessorFramework forDialogFragment() {
|
||||||
|
return sDialogFragmentAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FragmentManagerAccessorViaReflection<FragmentManager, Fragment> forFragmentManager() {
|
||||||
|
return sFragmentManagerAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FragmentActivityAccessorFramework forFragmentActivity() {
|
||||||
|
return sFragmentActivityAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FragmentAccessorFrameworkHoneycomb
|
||||||
|
implements FragmentAccessor<Fragment, FragmentManager> {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getFragmentManager(Fragment fragment) {
|
||||||
|
return fragment.getFragmentManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resources getResources(Fragment fragment) {
|
||||||
|
return fragment.getResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId(Fragment fragment) {
|
||||||
|
return fragment.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getTag(Fragment fragment) {
|
||||||
|
return fragment.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View getView(Fragment fragment) {
|
||||||
|
return fragment.getView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getChildFragmentManager(Fragment fragment) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||||
|
private static class FragmentAccessorFrameworkJellyBean
|
||||||
|
extends FragmentAccessorFrameworkHoneycomb {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getChildFragmentManager(Fragment fragment) {
|
||||||
|
return fragment.getChildFragmentManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DialogFragmentAccessorFramework
|
||||||
|
implements DialogFragmentAccessor<DialogFragment, Fragment, FragmentManager> {
|
||||||
|
private final FragmentAccessor<Fragment, FragmentManager> mFragmentAccessor;
|
||||||
|
|
||||||
|
public DialogFragmentAccessorFramework(
|
||||||
|
FragmentAccessor<Fragment, FragmentManager> fragmentAccessor) {
|
||||||
|
mFragmentAccessor = fragmentAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog getDialog(DialogFragment dialogFragment) {
|
||||||
|
return dialogFragment.getDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getFragmentManager(Fragment fragment) {
|
||||||
|
return mFragmentAccessor.getFragmentManager(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resources getResources(Fragment fragment) {
|
||||||
|
return mFragmentAccessor.getResources(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId(Fragment fragment) {
|
||||||
|
return mFragmentAccessor.getId(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getTag(Fragment fragment) {
|
||||||
|
return mFragmentAccessor.getTag(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View getView(Fragment fragment) {
|
||||||
|
return mFragmentAccessor.getView(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getChildFragmentManager(Fragment fragment) {
|
||||||
|
return mFragmentAccessor.getChildFragmentManager(fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FragmentActivityAccessorFramework
|
||||||
|
implements FragmentActivityAccessor<Activity, FragmentManager> {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getFragmentManager(Activity activity) {
|
||||||
|
return activity.getFragmentManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.view.View;
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
final class FragmentCompatSupportLib
|
||||||
|
extends FragmentCompat<Fragment, DialogFragment, FragmentManager, FragmentActivity> {
|
||||||
|
private static final FragmentAccessorSupportLib sFragmentAccessor =
|
||||||
|
new FragmentAccessorSupportLib();
|
||||||
|
private static final DialogFragmentAccessorSupportLib sDialogFragmentAccessor =
|
||||||
|
new DialogFragmentAccessorSupportLib();
|
||||||
|
private static final FragmentManagerAccessorViaReflection<FragmentManager, Fragment>
|
||||||
|
sFragmentManagerAccessor = new FragmentManagerAccessorViaReflection<>();
|
||||||
|
private static final FragmentActivityAccessorSupportLib sFragmentActivityAccessor =
|
||||||
|
new FragmentActivityAccessorSupportLib();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Fragment> getFragmentClass() {
|
||||||
|
return Fragment.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<DialogFragment> getDialogFragmentClass() {
|
||||||
|
return DialogFragment.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<FragmentActivity> getFragmentActivityClass() {
|
||||||
|
return FragmentActivity.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FragmentAccessorSupportLib forFragment() {
|
||||||
|
return sFragmentAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DialogFragmentAccessorSupportLib forDialogFragment() {
|
||||||
|
return sDialogFragmentAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FragmentManagerAccessor<FragmentManager, Fragment> forFragmentManager() {
|
||||||
|
return sFragmentManagerAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FragmentActivityAccessorSupportLib forFragmentActivity() {
|
||||||
|
return sFragmentActivityAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FragmentAccessorSupportLib
|
||||||
|
implements FragmentAccessor<Fragment, FragmentManager> {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getFragmentManager(Fragment fragment) {
|
||||||
|
return fragment.getFragmentManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resources getResources(Fragment fragment) {
|
||||||
|
return fragment.getResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId(Fragment fragment) {
|
||||||
|
return fragment.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getTag(Fragment fragment) {
|
||||||
|
return fragment.getTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View getView(Fragment fragment) {
|
||||||
|
return fragment.getView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getChildFragmentManager(Fragment fragment) {
|
||||||
|
return fragment.getChildFragmentManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DialogFragmentAccessorSupportLib extends FragmentAccessorSupportLib
|
||||||
|
implements DialogFragmentAccessor<DialogFragment, Fragment, FragmentManager> {
|
||||||
|
@Override
|
||||||
|
public Dialog getDialog(DialogFragment dialogFragment) {
|
||||||
|
return dialogFragment.getDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FragmentActivityAccessorSupportLib
|
||||||
|
implements FragmentActivityAccessor<FragmentActivity, FragmentManager> {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public FragmentManager getFragmentManager(FragmentActivity activity) {
|
||||||
|
return activity.getSupportFragmentManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.view.View;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public final class FragmentCompatUtil {
|
||||||
|
private FragmentCompatUtil() {}
|
||||||
|
|
||||||
|
public static boolean isDialogFragment(Object fragment) {
|
||||||
|
FragmentCompat supportLib = FragmentCompat.getSupportLibInstance();
|
||||||
|
if (supportLib != null && supportLib.getDialogFragmentClass().isInstance(fragment)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FragmentCompat framework = FragmentCompat.getFrameworkInstance();
|
||||||
|
if (framework != null && framework.getDialogFragmentClass().isInstance(fragment)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Object findFragmentForView(View view) {
|
||||||
|
Activity activity = ViewUtil.tryGetActivity(view);
|
||||||
|
if (activity == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return findFragmentForViewInActivity(activity, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Object findFragmentForViewInActivity(Activity activity, View view) {
|
||||||
|
FragmentCompat supportLib = FragmentCompat.getSupportLibInstance();
|
||||||
|
|
||||||
|
// Try the support library version if it is present and the activity is FragmentActivity.
|
||||||
|
if (supportLib != null && supportLib.getFragmentActivityClass().isInstance(activity)) {
|
||||||
|
Object fragment = findFragmentForViewInActivity(supportLib, activity, view);
|
||||||
|
if (fragment != null) {
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try the actual Android runtime version if we are on a sufficiently high API level for it to
|
||||||
|
// exist. Note that technically we can have both the support library and the framework
|
||||||
|
// version in the same object instance due to FragmentActivity extending Activity (which has
|
||||||
|
// fragment support in the system).
|
||||||
|
FragmentCompat framework = FragmentCompat.getFrameworkInstance();
|
||||||
|
if (framework != null) {
|
||||||
|
Object fragment = findFragmentForViewInActivity(framework, activity, view);
|
||||||
|
if (fragment != null) {
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object findFragmentForViewInActivity(
|
||||||
|
FragmentCompat compat, Activity activity, View view) {
|
||||||
|
Object fragmentManager = compat.forFragmentActivity().getFragmentManager(activity);
|
||||||
|
if (fragmentManager != null) {
|
||||||
|
return findFragmentForViewInFragmentManager(compat, fragmentManager, view);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Object findFragmentForViewInFragmentManager(
|
||||||
|
FragmentCompat compat, Object fragmentManager, View view) {
|
||||||
|
List<?> fragments = compat.forFragmentManager().getAddedFragments(fragmentManager);
|
||||||
|
|
||||||
|
if (fragments != null) {
|
||||||
|
for (int i = 0, N = fragments.size(); i < N; ++i) {
|
||||||
|
Object fragment = fragments.get(i);
|
||||||
|
Object result = findFragmentForViewInFragment(compat, fragment, view);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Object findFragmentForViewInFragment(
|
||||||
|
FragmentCompat compat, Object fragment, View view) {
|
||||||
|
FragmentAccessor accessor = compat.forFragment();
|
||||||
|
|
||||||
|
if (accessor.getView(fragment) == view) {
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object childFragmentManager = accessor.getChildFragmentManager(fragment);
|
||||||
|
if (childFragmentManager != null) {
|
||||||
|
return findFragmentForViewInFragmentManager(compat, childFragmentManager, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface FragmentManagerAccessor<FRAGMENT_MANAGER, FRAGMENT> {
|
||||||
|
@Nullable
|
||||||
|
List<FRAGMENT> getAddedFragments(FRAGMENT_MANAGER fragmentManager);
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public final class ReflectionUtil {
|
||||||
|
private ReflectionUtil() {}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Class<?> tryGetClassForName(String className) {
|
||||||
|
try {
|
||||||
|
return Class.forName(className);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Field tryGetDeclaredField(Class<?> theClass, String fieldName) {
|
||||||
|
try {
|
||||||
|
return theClass.getDeclaredField(fieldName);
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
Log.e(
|
||||||
|
ReflectionUtil.class.getCanonicalName(),
|
||||||
|
String.format("Could not retrieve %s field from %s", fieldName, theClass),
|
||||||
|
e);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static Object getFieldValue(Field field, Object target) {
|
||||||
|
try {
|
||||||
|
return field.get(target);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.util.Log;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/** Copied from Stetho. */
|
||||||
|
public class ResourcesUtil {
|
||||||
|
private ResourcesUtil() {}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public static String getIdStringQuietly(Object idContext, @Nullable Resources r, int resourceId) {
|
||||||
|
try {
|
||||||
|
return getIdString(r, resourceId);
|
||||||
|
} catch (Resources.NotFoundException e) {
|
||||||
|
String idString = getFallbackIdString(resourceId);
|
||||||
|
Log.w(
|
||||||
|
ResourcesUtil.class.getCanonicalName(),
|
||||||
|
"Unknown identifier encountered on " + idContext + ": " + idString);
|
||||||
|
return idString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getIdString(@Nullable Resources r, int resourceId)
|
||||||
|
throws Resources.NotFoundException {
|
||||||
|
if (r == null) {
|
||||||
|
return getFallbackIdString(resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
String prefix;
|
||||||
|
String prefixSeparator;
|
||||||
|
switch (getResourcePackageId(resourceId)) {
|
||||||
|
case 0x7f:
|
||||||
|
prefix = "";
|
||||||
|
prefixSeparator = "";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
prefix = r.getResourcePackageName(resourceId);
|
||||||
|
prefixSeparator = ":";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String typeName = r.getResourceTypeName(resourceId);
|
||||||
|
String entryName = r.getResourceEntryName(resourceId);
|
||||||
|
|
||||||
|
StringBuilder sb =
|
||||||
|
new StringBuilder(
|
||||||
|
1
|
||||||
|
+ prefix.length()
|
||||||
|
+ prefixSeparator.length()
|
||||||
|
+ typeName.length()
|
||||||
|
+ 1
|
||||||
|
+ entryName.length());
|
||||||
|
sb.append("@");
|
||||||
|
sb.append(prefix);
|
||||||
|
sb.append(prefixSeparator);
|
||||||
|
sb.append(typeName);
|
||||||
|
sb.append("/");
|
||||||
|
sb.append(entryName);
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getFallbackIdString(int resourceId) {
|
||||||
|
return "#" + Integer.toHexString(resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getResourcePackageId(int id) {
|
||||||
|
return (id >>> 24) & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewParent;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
final class ViewUtil {
|
||||||
|
private ViewUtil() {}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static Activity tryGetActivity(View view) {
|
||||||
|
if (view == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context context = view.getContext();
|
||||||
|
|
||||||
|
Activity activityFromContext = tryGetActivity(context);
|
||||||
|
if (activityFromContext != null) {
|
||||||
|
return activityFromContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewParent parent = view.getParent();
|
||||||
|
if (parent instanceof View) {
|
||||||
|
View parentView = (View) parent;
|
||||||
|
return tryGetActivity(parentView);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static Activity tryGetActivity(Context context) {
|
||||||
|
while (context != null) {
|
||||||
|
if (context instanceof Activity) {
|
||||||
|
return (Activity) context;
|
||||||
|
} else if (context instanceof ContextWrapper) {
|
||||||
|
context = ((ContextWrapper) context).getBaseContext();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -86,7 +86,6 @@ ext.deps = [
|
|||||||
junit : 'junit:junit:4.12',
|
junit : 'junit:junit:4.12',
|
||||||
hamcrest : 'org.hamcrest:hamcrest-library:1.3',
|
hamcrest : 'org.hamcrest:hamcrest-library:1.3',
|
||||||
mockito : 'org.mockito:mockito-core:1.9.5',
|
mockito : 'org.mockito:mockito-core:1.9.5',
|
||||||
stetho : 'com.facebook.stetho:stetho:1.5.1',
|
|
||||||
okhttp3 : 'com.squareup.okhttp3:okhttp:3.14.1',
|
okhttp3 : 'com.squareup.okhttp3:okhttp:3.14.1',
|
||||||
leakcanary : 'com.squareup.leakcanary:leakcanary-android:1.6.3',
|
leakcanary : 'com.squareup.leakcanary:leakcanary-android:1.6.3',
|
||||||
testCore : 'androidx.test:core:1.1.0',
|
testCore : 'androidx.test:core:1.1.0',
|
||||||
|
|||||||
Reference in New Issue
Block a user