From e57ad4ee37b02cd4c9e10a97d7a1d2b799204d7d Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 7 Nov 2018 18:28:47 -0800 Subject: [PATCH] Fix IllegalArgumentException when dismissing ReactModalHostView Summary: This diff fixes an IllegalArgumentException when dismissing ReactModalHostView. I wasn't able to reproduce this error because this is likely created by a race condition. Reviewed By: axe-fb Differential Revision: D12916787 fbshipit-source-id: b071ffc4c251f2a613bb1270de005def56818376 --- .../java/com/facebook/react/views/common/BUCK | 1 + .../react/views/common/ContextUtils.java | 37 +++++++++++++++++++ .../java/com/facebook/react/views/modal/BUCK | 1 + .../react/views/modal/ReactModalHostView.java | 9 +++-- 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/views/common/ContextUtils.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK index d78d4b99697..ea90e56cf58 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/common/BUCK @@ -4,6 +4,7 @@ rn_android_library( name = "common", srcs = glob(["*.java"]), provided_deps = [ + react_native_dep("third-party/java/jsr-305:jsr-305"), react_native_dep("third-party/android/support/v4:lib-support-v4"), ], visibility = [ diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/common/ContextUtils.java b/ReactAndroid/src/main/java/com/facebook/react/views/common/ContextUtils.java new file mode 100644 index 00000000000..62ef0cd8a43 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/views/common/ContextUtils.java @@ -0,0 +1,37 @@ +package com.facebook.react.views.common; + +import android.content.Context; +import android.content.ContextWrapper; +import javax.annotation.Nullable; + +/** + * Class containing static methods involving manipulations of Contexts and their related subclasses. + */ +public class ContextUtils { + + /** + * Returns the nearest context in the chain (as defined by ContextWrapper.getBaseContext()) which + * is an instance of the specified type, or null if one could not be found + * + * @param context Initial context + * @param clazz Class instance to look for + * @param + * @return the first context which is an instance of the specified class, or null if none exists + */ + public static @Nullable T findContextOfType( + @Nullable Context context, Class clazz) { + while (!(clazz.isInstance(context))) { + if (context instanceof ContextWrapper) { + Context baseContext = ((ContextWrapper) context).getBaseContext(); + if (context == baseContext) { + return null; + } else { + context = baseContext; + } + } else { + return null; + } + } + return (T) context; + } +} diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK index b2d013012e6..f3cef9f54e7 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/BUCK @@ -17,6 +17,7 @@ rn_android_library( react_native_target("java/com/facebook/react/touch:touch"), react_native_target("java/com/facebook/react/uimanager:uimanager"), react_native_target("java/com/facebook/react/uimanager/annotations:annotations"), + react_native_target("java/com/facebook/react/views/common:common"), react_native_target("java/com/facebook/react/views/view:view"), react_native_target("res:modal"), ], diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java index ff3408a375a..7ec8ae51691 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.java @@ -28,6 +28,7 @@ import com.facebook.react.uimanager.JSTouchDispatcher; import com.facebook.react.uimanager.RootView; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.EventDispatcher; +import com.facebook.react.views.common.ContextUtils; import com.facebook.react.views.view.ReactViewGroup; import java.util.ArrayList; import javax.annotation.Nullable; @@ -123,9 +124,11 @@ public class ReactModalHostView extends ViewGroup implements LifecycleEventListe private void dismiss() { if (mDialog != null) { - Activity currentActivity = getCurrentActivity(); - if (mDialog.isShowing() && (currentActivity == null || !currentActivity.isFinishing())) { - mDialog.dismiss(); + if (mDialog.isShowing()) { + Activity dialogContext = ContextUtils.findContextOfType(mDialog.getContext(), Activity.class); + if (dialogContext == null || !dialogContext.isFinishing()) { + mDialog.dismiss(); + } } mDialog = null;