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:
Zac Sweers
2020-01-28 05:21:55 -08:00
committed by Facebook Github Bot
parent bdd4516dc4
commit 48d6ea4c30
19 changed files with 786 additions and 10 deletions

View File

@@ -63,7 +63,6 @@ android {
implementation deps.soloader
implementation deps.jsr305
implementation deps.supportAppCompat
implementation deps.stetho
testImplementation deps.mockito
testImplementation deps.robolectric

View File

@@ -21,8 +21,12 @@ android {
implementation project(':android')
implementation deps.fresco
implementation deps.frescoFlipper
implementation deps.frescoStetho
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'
}
}
}

View File

@@ -14,9 +14,9 @@ import com.facebook.flipper.core.FlipperObject;
import com.facebook.flipper.plugins.inspector.Named;
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
import com.facebook.flipper.plugins.inspector.Touch;
import com.facebook.stetho.common.android.FragmentActivityAccessor;
import com.facebook.stetho.common.android.FragmentCompat;
import com.facebook.stetho.common.android.FragmentManagerAccessor;
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentActivityAccessor;
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentCompat;
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentManagerAccessor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

View File

@@ -15,7 +15,7 @@ import com.facebook.flipper.core.FlipperObject;
import com.facebook.flipper.plugins.inspector.Named;
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
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.Collections;
import java.util.List;

View File

@@ -15,7 +15,7 @@ import com.facebook.flipper.core.FlipperObject;
import com.facebook.flipper.plugins.inspector.Named;
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
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.Collections;
import java.util.List;

View File

@@ -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.AccessibilityUtil;
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.util.ArrayList;
import java.util.Arrays;

View File

@@ -24,7 +24,7 @@ import com.facebook.flipper.plugins.inspector.InspectorValue;
import com.facebook.flipper.plugins.inspector.Named;
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
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.List;
import javax.annotation.Nullable;

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -86,7 +86,6 @@ ext.deps = [
junit : 'junit:junit:4.12',
hamcrest : 'org.hamcrest:hamcrest-library:1.3',
mockito : 'org.mockito:mockito-core:1.9.5',
stetho : 'com.facebook.stetho:stetho:1.5.1',
okhttp3 : 'com.squareup.okhttp3:okhttp:3.14.1',
leakcanary : 'com.squareup.leakcanary:leakcanary-android:1.6.3',
testCore : 'androidx.test:core:1.1.0',