From 92ebb298e2e5ad640754e09ce3a37d3de1d28f58 Mon Sep 17 00:00:00 2001 From: Andy Zolyak Date: Wed, 1 Jun 2022 08:07:40 -0700 Subject: [PATCH] Fix ReactEditText so it works with Android Emoji2 automatic support (#33920) Summary: tldr; `ReactEditText` and Android's emoji support in Android's AppCompat 1.4.0 / 1.4.x conflict in an odd way, causing NPEs. `ReactEditText` defines an `InternalKeyListener`, `mKeyListener`, that it uses to make sure input from all keyboards works correctly. This listener is normally initialized at the end of the constructor. Unfortunately, some versions of `AppCompatEditText`, most notably the version in the App Compat `1.4.0-alpha0x`, the [minimum version required for the Play Store's emoji compliance](https://developer.android.com/guide/topics/ui/look-and-feel/emoji2#appcompat) call `setInputType` from `AppCompatEditText`'s constructor. `ReactEditText` operates on the key listener inside of `setInputType` and since the `AppCompatEditText` constructor is called via call to `super` before the key listener is initialized, these versions of app compat can cause NPEs when used with React Native. The fix is simple; check to see if `mKeyListener` is null, and initialize it if it is. This is necessary in both the constructor and inside of `setInputType`. ## Changelog https://github.com/facebook/react-native/wiki/Changelog [Android] [Fixed] - NPE in `ReactEditText.setInputType` when React Native is used with some versions of a AppCompat 1.4.x. (and possibly others) Pull Request resolved: https://github.com/facebook/react-native/pull/33920 Test Plan: 1. Build an app with both React Native and load it inside an app that is using AppCompat 1.4.x 2. Add a text field using React Native. 3. Open the screen of the app that contains the text field. If you're working from this branch, you'll be fine. If you're working from main you'll get an NPE. I can put together a test repo if needed. Reviewed By: kacieb Differential Revision: D36802622 Pulled By: cortinico fbshipit-source-id: e7646da9a1ef0e0334152aecab0f972ca25092ec --- .../facebook/react/views/textinput/ReactEditText.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 51deec2f262075..4847b9b5d86e7d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -101,7 +101,7 @@ public class ReactEditText extends AppCompatEditText private @Nullable SelectionWatcher mSelectionWatcher; private @Nullable ContentSizeWatcher mContentSizeWatcher; private @Nullable ScrollWatcher mScrollWatcher; - private final InternalKeyListener mKeyListener; + private InternalKeyListener mKeyListener; private boolean mDetectScrollMovement = false; private boolean mOnKeyPress = false; private TextAttributes mTextAttributes; @@ -140,7 +140,9 @@ public ReactEditText(Context context) { mListeners = null; mTextWatcherDelegator = null; mStagedInputType = getInputType(); - mKeyListener = new InternalKeyListener(); + if (mKeyListener == null) { + mKeyListener = new InternalKeyListener(); + } mScrollWatcher = null; mTextAttributes = new TextAttributes(); @@ -451,6 +453,10 @@ public void setInputType(int type) { // We override the KeyListener so that all keys on the soft input keyboard as well as hardware // keyboards work. Some KeyListeners like DigitsKeyListener will display the keyboard but not // accept all input from it + if (mKeyListener == null) { + mKeyListener = new InternalKeyListener(); + } + mKeyListener.setInputType(type); setKeyListener(mKeyListener); }