Skip to content

Commit

Permalink
Set caretHidden to true to fix the Xiaomi crash
Browse files Browse the repository at this point in the history
Summary:
After monitoring scuba for a few days,  previous fixes(D23301714 D23331828 (07a597a)) don't work as expected.

I managed to test this issue on a Xiaomi device, the crash didn't happen but the there was a popup "Frequetly used email" on top of email edit text:

{F317216473}

Getting rid of the popup probably be the right fix.

For more context see #27204

Changelog: [Android] - Set caretHidden to true to fix the Xiaomi crash

Reviewed By: mdvacca

Differential Revision: D23451929

fbshipit-source-id: 521931422f3a46a056a9faa4b10fe93cf4732db0
  • Loading branch information
luluwu2032 authored and facebook-github-bot committed Sep 2, 2020
1 parent 59ddd7c commit b5b4a70
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 19 deletions.
9 changes: 6 additions & 3 deletions Libraries/Components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,6 @@ export type Props = $ReadOnly<{|
*
* - `visible-password`
*
* On Android devices manufactured by Xiaomi with Android Q, 'email-address'
* type will be replaced in native by 'default' to prevent a system related crash.
*/
keyboardType?: ?KeyboardType,

Expand Down Expand Up @@ -685,7 +683,12 @@ export type Props = $ReadOnly<{|

/**
* If `true`, caret is hidden. The default value is `false`.
* This property is supported only for single-line TextInput component on iOS.
*
* On Android devices manufactured by Xiaomi with Android Q,
* when keyboardType equals 'email-address'this will be set
* in native to 'true' to prevent a system related crash. This
* will cause cursor to be diabled as a side-effect.
*
*/
caretHidden?: ?boolean,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,8 @@ namespace JS {
RCTRequired<NSString *> Model;
NSString *ServerHost;
RCTRequired<NSString *> uiMode;
RCTRequired<NSString *> Brand;
RCTRequired<NSString *> Manufacturer;
};

/** Initialize with a set of values */
Expand Down Expand Up @@ -3391,6 +3393,10 @@ inline JS::NativePlatformConstantsAndroid::Constants::Builder::Builder(const Inp
d[@"ServerHost"] = ServerHost;
auto uiMode = i.uiMode.get();
d[@"uiMode"] = uiMode;
auto Brand = i.Brand.get();
d[@"Brand"] = Brand;
auto Manufacturer = i.Manufacturer.get();
d[@"Manufacturer"] = Manufacturer;
return d;
}) {}
inline JS::NativePlatformConstantsAndroid::Constants::Builder::Builder(Constants i) : _factory(^{
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Utilities/NativePlatformConstantsAndroid.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export interface Spec extends TurboModule {
Model: string,
ServerHost?: string,
uiMode: string,
Brand: string,
Manufacturer: string,
|};
+getAndroidID: () => string;
}
Expand Down
2 changes: 2 additions & 0 deletions Libraries/Utilities/Platform.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const Platform = {
Model: string,
ServerHost?: string,
uiMode: string,
Brand: string,
Manufacturer: string,
|} {
if (this.__constants == null) {
this.__constants = NativePlatformConstantsAndroid.getConstants();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ public NativePlatformConstantsAndroidSpec(ReactApplicationContext reactContext)
Map<String, Object> constants = getTypedExportedConstants();
if (ReactBuildConfig.DEBUG || ReactBuildConfig.IS_INTERNAL_BUILD) {
Set<String> obligatoryFlowConstants = new HashSet<>(Arrays.asList(
"Brand",
"Serial",
"Fingerprint",
"uiMode",
"Version",
"reactNativeVersion",
"Model",
"Manufacturer",
"isTesting",
"Release"
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public String getName() {
constants.put("Serial", Build.SERIAL);
constants.put("Fingerprint", Build.FINGERPRINT);
constants.put("Model", Build.MODEL);
constants.put("Manufacturer", Build.MANUFACTURER);
constants.put("Brand", Build.BRAND);
if (ReactBuildConfig.DEBUG) {
constants.put(
"ServerHost",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,21 +392,8 @@ public void setInputType(int type) {
// Input type password defaults to monospace font, so we need to re-apply the font
super.setTypeface(tf);

int inputType = type;

// Set InputType to TYPE_CLASS_TEXT (the default one for Android) to fix a crash on Xiaomi
// devices with Android Q. This crash happens when focusing on a email EditText within a
// ScrollView, a prompt will be triggered but the system fail to locate it properly.
// Here is an example post discussing about this issue:
// https://github.com/facebook/react-native/issues/27204
if (inputType == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
&& Build.VERSION.SDK_INT == Build.VERSION_CODES.Q
&& Build.MANUFACTURER.startsWith("Xiaomi")) {
inputType = InputType.TYPE_CLASS_TEXT;
}

super.setInputType(inputType);
mStagedInputType = inputType;
super.setInputType(type);
mStagedInputType = type;

/**
* If set forces multiline on input, because of a restriction on Android source that enables
Expand All @@ -421,7 +408,7 @@ 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
mKeyListener.setInputType(inputType);
mKeyListener.setInputType(type);
setKeyListener(mKeyListener);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,19 @@ public void setCursorColor(ReactEditText view, @Nullable Integer color) {

@ReactProp(name = "caretHidden", defaultBoolean = false)
public void setCaretHidden(ReactEditText view, boolean caretHidden) {
// Set cursor's visibility to False to fix a crash on some Xiaomi devices with Android Q. This
// crash happens when focusing on a email EditText, during which a prompt will be triggered but
// the system fail to locate it properly. Here is an example post discussing about this
// issue: https://github.com/facebook/react-native/issues/27204
String manufacturer = Build.MANUFACTURER.toLowerCase();
if ((view.getInputType() == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|| view.getInputType() == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS)
&& Build.VERSION.SDK_INT == Build.VERSION_CODES.Q
&& manufacturer.contains("xiaomi")) {
view.setCursorVisible(false);
return;
}

view.setCursorVisible(!caretHidden);
}

Expand Down

0 comments on commit b5b4a70

Please sign in to comment.