diff --git a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java index 3eb7b72c4..3febc2913 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java +++ b/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManagerImpl.java @@ -11,8 +11,6 @@ package com.facebook.react; import javax.annotation.Nullable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -26,12 +24,8 @@ import android.app.Application; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; -import android.os.Build; import android.os.Bundle; -import android.util.DisplayMetrics; -import android.view.Display; import android.view.View; -import android.view.WindowManager; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; @@ -285,7 +279,7 @@ import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_START // TODO(9577825): remove this ApplicationHolder.setApplication((Application) applicationContext.getApplicationContext()); - setDisplayMetrics(applicationContext); + DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(applicationContext); mApplicationContext = applicationContext; mCurrentActivity = currentActivity; @@ -328,40 +322,6 @@ import static com.facebook.react.bridge.ReactMarkerConstants.RUN_JS_BUNDLE_START SoLoader.init(applicationContext, /* native exopackage */ false); } - private static void setDisplayMetrics(Context context) { - DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); - DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); - - DisplayMetrics screenDisplayMetrics = new DisplayMetrics(); - screenDisplayMetrics.setTo(displayMetrics); - WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - Display display = wm.getDefaultDisplay(); - - // Get the real display metrics if we are using API level 17 or higher. - // The real metrics include system decor elements (e.g. soft menu bar). - // - // See: http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics) - if (Build.VERSION.SDK_INT >= 17) { - display.getRealMetrics(screenDisplayMetrics); - } else { - // For 14 <= API level <= 16, we need to invoke getRawHeight and getRawWidth to get the real dimensions. - // Since react-native only supports API level 16+ we don't have to worry about other cases. - // - // Reflection exceptions are rethrown at runtime. - // - // See: http://stackoverflow.com/questions/14341041/how-to-get-real-screen-height-and-width/23861333#23861333 - try { - Method mGetRawH = Display.class.getMethod("getRawHeight"); - Method mGetRawW = Display.class.getMethod("getRawWidth"); - screenDisplayMetrics.widthPixels = (Integer) mGetRawW.invoke(display); - screenDisplayMetrics.heightPixels = (Integer) mGetRawH.invoke(display); - } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { - throw new RuntimeException("Error getting real dimensions for API level < 17", e); - } - } - DisplayMetricsHolder.setScreenDisplayMetrics(screenDisplayMetrics); - } - /** * Trigger react context initialization asynchronously in a background async task. This enables * applications to pre-load the application JS, and execute global code before diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java index c465073f8..9c3e6baf5 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/DisplayMetricsHolder.java @@ -9,7 +9,18 @@ package com.facebook.react.uimanager; +import android.content.Context; +import android.os.Build; import android.util.DisplayMetrics; +import android.view.Display; +import android.view.WindowManager; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.annotation.Nullable; + +import com.facebook.infer.annotation.Assertions; /** * Holds an instance of the current DisplayMetrics so we don't have to thread it through all the @@ -22,8 +33,8 @@ import android.util.DisplayMetrics; */ public class DisplayMetricsHolder { - private static DisplayMetrics sWindowDisplayMetrics; - private static DisplayMetrics sScreenDisplayMetrics; + private static @Nullable DisplayMetrics sWindowDisplayMetrics; + private static @Nullable DisplayMetrics sScreenDisplayMetrics; /** * @deprecated Use {@link #setScreenDisplayMetrics(DisplayMetrics)} instead. See comment above as @@ -32,6 +43,46 @@ public class DisplayMetricsHolder { public static void setWindowDisplayMetrics(DisplayMetrics displayMetrics) { sWindowDisplayMetrics = displayMetrics; } + + public static void initDisplayMetricsIfNotInitialized(Context context) { + if (DisplayMetricsHolder.getScreenDisplayMetrics() != null) { + return; + } + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); + + DisplayMetrics screenDisplayMetrics = new DisplayMetrics(); + screenDisplayMetrics.setTo(displayMetrics); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Assertions.assertNotNull( + wm, + "WindowManager is null!"); + Display display = wm.getDefaultDisplay(); + + // Get the real display metrics if we are using API level 17 or higher. + // The real metrics include system decor elements (e.g. soft menu bar). + // + // See: http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics) + if (Build.VERSION.SDK_INT >= 17) { + display.getRealMetrics(screenDisplayMetrics); + } else { + // For 14 <= API level <= 16, we need to invoke getRawHeight and getRawWidth to get the real dimensions. + // Since react-native only supports API level 16+ we don't have to worry about other cases. + // + // Reflection exceptions are rethrown at runtime. + // + // See: http://stackoverflow.com/questions/14341041/how-to-get-real-screen-height-and-width/23861333#23861333 + try { + Method mGetRawH = Display.class.getMethod("getRawHeight"); + Method mGetRawW = Display.class.getMethod("getRawWidth"); + screenDisplayMetrics.widthPixels = (Integer) mGetRawW.invoke(display); + screenDisplayMetrics.heightPixels = (Integer) mGetRawH.invoke(display); + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { + throw new RuntimeException("Error getting real dimensions for API level < 17", e); + } + } + DisplayMetricsHolder.setScreenDisplayMetrics(screenDisplayMetrics); + } /** * @deprecated Use {@link #getScreenDisplayMetrics()} instead. See comment above as to why this diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java index 457fea3ef..2503b285d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModule.java @@ -23,6 +23,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.debug.NotThreadSafeViewHierarchyUpdateDebugListener; import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.systrace.Systrace; @@ -76,6 +77,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements List viewManagerList, UIImplementation uiImplementation) { super(reactContext); + DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext); mEventDispatcher = new EventDispatcher(reactContext); mModuleConstants = createConstants(viewManagerList); mUIImplementation = uiImplementation; diff --git a/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java b/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java index 97e9d6e53..b34737780 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/RootViewTest.java @@ -81,8 +81,7 @@ public class RootViewTest { mCatalystInstanceMock = ReactTestHelper.createMockCatalystInstance(); mReactContext = new ReactApplicationContext(RuntimeEnvironment.application); mReactContext.initializeWithInstance(mCatalystInstanceMock); - DisplayMetrics displayMetrics = mReactContext.getResources().getDisplayMetrics(); - DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); + DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(mReactContext); UIManagerModule uiManagerModuleMock = mock(UIManagerModule.class); when(mCatalystInstanceMock.getNativeModule(UIManagerModule.class)) diff --git a/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.java b/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.java index bcc930fa6..2f6eea4b7 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/uimanager/ReactPropConstantsTest.java @@ -13,7 +13,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import android.util.DisplayMetrics; import android.view.View; import com.facebook.react.bridge.ReactApplicationContext; @@ -146,9 +145,6 @@ public class ReactPropConstantsTest { public void testNativePropsIncludeCorrectTypes() { List viewManagers = Arrays.asList(new ViewManagerUnderTest()); ReactApplicationContext reactContext = new ReactApplicationContext(RuntimeEnvironment.application); - DisplayMetrics displayMetrics = reactContext.getResources().getDisplayMetrics(); - DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); - DisplayMetricsHolder.setScreenDisplayMetrics(displayMetrics); UIManagerModule uiManagerModule = new UIManagerModule( reactContext, viewManagers, diff --git a/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleConstantsTest.java b/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleConstantsTest.java index 0f8b7ec91..5d757eb2f 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleConstantsTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleConstantsTest.java @@ -13,8 +13,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import android.util.DisplayMetrics; - import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.common.MapBuilder; @@ -58,10 +56,6 @@ public class UIManagerModuleConstantsTest { public void setUp() { mReactContext = new ReactApplicationContext(RuntimeEnvironment.application); mUIImplementation = mock(UIImplementation.class); - - DisplayMetrics displayMetrics = mReactContext.getResources().getDisplayMetrics(); - DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); - DisplayMetricsHolder.setScreenDisplayMetrics(displayMetrics); } @Test diff --git a/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleTest.java b/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleTest.java index 3b9cd7706..8c3fa60a0 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/uimanager/UIManagerModuleTest.java @@ -14,7 +14,6 @@ import java.util.Arrays; import java.util.List; import android.graphics.Color; -import android.util.DisplayMetrics; import android.view.Choreographer; import android.view.View; import android.view.ViewGroup; @@ -108,10 +107,6 @@ public class UIManagerModuleTest { mReactContext = new ReactApplicationContext(RuntimeEnvironment.application); mReactContext.initializeWithInstance(mCatalystInstanceMock); - DisplayMetrics displayMetrics = mReactContext.getResources().getDisplayMetrics(); - DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); - DisplayMetricsHolder.setScreenDisplayMetrics(displayMetrics); - UIManagerModule uiManagerModuleMock = mock(UIManagerModule.class); when(mCatalystInstanceMock.getNativeModule(UIManagerModule.class)) .thenReturn(uiManagerModuleMock); diff --git a/ReactAndroid/src/test/java/com/facebook/react/views/text/ReactTextTest.java b/ReactAndroid/src/test/java/com/facebook/react/views/text/ReactTextTest.java index 257f77a89..7d8f15829 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/views/text/ReactTextTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/views/text/ReactTextTest.java @@ -24,7 +24,6 @@ import android.text.TextUtils; import android.text.style.AbsoluteSizeSpan; import android.text.style.StrikethroughSpan; import android.text.style.UnderlineSpan; -import android.util.DisplayMetrics; import android.view.Choreographer; import android.widget.TextView; @@ -34,7 +33,6 @@ import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactTestHelper; -import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.ReactChoreographer; import com.facebook.react.uimanager.UIImplementation; import com.facebook.react.uimanager.UIManagerModule; @@ -428,9 +426,6 @@ public class ReactTextTest { public UIManagerModule getUIManagerModule() { ReactApplicationContext reactContext = ReactTestHelper.createCatalystContextForTest(); - DisplayMetrics displayMetrics = reactContext.getResources().getDisplayMetrics(); - DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); - DisplayMetricsHolder.setScreenDisplayMetrics(displayMetrics); List viewManagers = Arrays.asList( new ViewManager[] { new ReactTextViewManager(), diff --git a/ReactAndroid/src/test/java/com/facebook/react/views/textinput/TextInputTest.java b/ReactAndroid/src/test/java/com/facebook/react/views/textinput/TextInputTest.java index 630c80a72..cd5243bef 100644 --- a/ReactAndroid/src/test/java/com/facebook/react/views/textinput/TextInputTest.java +++ b/ReactAndroid/src/test/java/com/facebook/react/views/textinput/TextInputTest.java @@ -13,7 +13,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import android.util.DisplayMetrics; import android.view.Choreographer; import android.widget.EditText; @@ -23,7 +22,6 @@ import com.facebook.react.bridge.JavaOnlyArray; import com.facebook.react.bridge.JavaOnlyMap; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactTestHelper; -import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.ReactChoreographer; import com.facebook.react.uimanager.UIImplementation; import com.facebook.react.uimanager.UIManagerModule; @@ -182,9 +180,6 @@ public class TextInputTest { new ViewManager[] { new ReactTextInputManager(), }); - DisplayMetrics displayMetrics = reactContext.getResources().getDisplayMetrics(); - DisplayMetricsHolder.setWindowDisplayMetrics(displayMetrics); - DisplayMetricsHolder.setScreenDisplayMetrics(displayMetrics); UIManagerModule uiManagerModule = new UIManagerModule( reactContext, viewManagers,