Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit e292632

Browse files
authored
[Android] Fix TextInputType.none for devices with physical keyboard (#49980)
## Description This PR fixes an issue where keystrokes aren't received on Android devices with physical keyboards (e.g. rugged Zebra devices) when `keyboardType` is set to `TextInputType.none` on a `TextField`. The logic in `setTextInputClient` and `canShowTextInput` created an `inputTarget` with `InputTarget.Type.NO_TARGET` which caused the [input connection to short circuit](https://github.com/flutter/engine/blob/main/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java#L296) and not be established. Bug introduction PR: #26585 ## Related Issue flutter/flutter#89983 ## Unit Test Notes - The existing `showTextInput_textInputTypeNone()` stays green after update. - `inputConnection_textInputTypeNone()` updated to `assertNotNull`. I would make this more specific, but this is my first venture into the Flutter engine and don't know enough about those connection attributes. ## Demo Video below with Zebra MC9300 device. This issue can also be reproduced in a standard android emulator. Simply add a `TextField`, configure `keyboardType` to be `TextInputType.none` and attempt to enter text after running and giving focus to textfield. Before https://github.com/flutter/engine/assets/1988098/348ca061-b8b9-4483-956e-0732c1238207 After https://github.com/flutter/engine/assets/1988098/b65c7251-59b4-4c73-9b85-7ac03f47a7e4 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [ ] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [ ] I updated/added relevant documentation (doc comments with `///`). - [x] I signed the [CLA]. - [x] All existing and new tests are passing.
1 parent 0eb7b10 commit e292632

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -376,16 +376,11 @@ public void sendTextInputAppPrivateCommand(@NonNull String action, @NonNull Bund
376376
mImm.sendAppPrivateCommand(mView, action, data);
377377
}
378378

379-
private boolean canShowTextInput() {
380-
if (configuration == null || configuration.inputType == null) {
381-
return true;
382-
}
383-
return configuration.inputType.type != TextInputChannel.TextInputType.NONE;
384-
}
385-
386379
@VisibleForTesting
387380
void showTextInput(View view) {
388-
if (canShowTextInput()) {
381+
if (configuration == null
382+
|| configuration.inputType == null
383+
|| configuration.inputType.type != TextInputChannel.TextInputType.NONE) {
389384
view.requestFocus();
390385
mImm.showSoftInput(view, 0);
391386
} else {
@@ -409,11 +404,7 @@ void setTextInputClient(int client, TextInputChannel.Configuration configuration
409404
// Call notifyViewExited on the previous field.
410405
notifyViewExited();
411406
this.configuration = configuration;
412-
if (canShowTextInput()) {
413-
inputTarget = new InputTarget(InputTarget.Type.FRAMEWORK_CLIENT, client);
414-
} else {
415-
inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, client);
416-
}
407+
inputTarget = new InputTarget(InputTarget.Type.FRAMEWORK_CLIENT, client);
417408

418409
mEditable.removeEditingStateListener(this);
419410
mEditable =

shell/platform/android/test/io/flutter/plugin/editing/TextInputPluginTest.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.flutter.plugin.editing;
22

33
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
45
import static org.junit.Assert.assertThrows;
56
import static org.junit.Assert.assertTrue;
67
import static org.mockito.AdditionalMatchers.aryEq;
@@ -1176,8 +1177,8 @@ public void destroy_clearTextInputMethodHandler() {
11761177

11771178
@SuppressWarnings("deprecation")
11781179
// DartExecutor.send is deprecated.
1179-
@Test
1180-
public void inputConnection_createsActionFromEnter() throws JSONException {
1180+
private void verifyInputConnection(TextInputChannel.TextInputType textInputType)
1181+
throws JSONException {
11811182
TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
11821183
FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
11831184
View testView = new View(ctx);
@@ -1194,7 +1195,7 @@ public void inputConnection_createsActionFromEnter() throws JSONException {
11941195
true,
11951196
false,
11961197
TextInputChannel.TextCapitalization.NONE,
1197-
new TextInputChannel.InputType(TextInputChannel.TextInputType.TEXT, false, false),
1198+
new TextInputChannel.InputType(textInputType, false, false),
11981199
null,
11991200
null,
12001201
null,
@@ -1232,6 +1233,16 @@ public void inputConnection_createsActionFromEnter() throws JSONException {
12321233
new String[] {"0", "TextInputAction.done"});
12331234
}
12341235

1236+
@Test
1237+
public void inputConnection_createsActionFromEnter() throws JSONException {
1238+
verifyInputConnection(TextInputChannel.TextInputType.TEXT);
1239+
}
1240+
1241+
@Test
1242+
public void inputConnection_respondsToKeyEvents_textInputTypeNone() throws JSONException {
1243+
verifyInputConnection(TextInputChannel.TextInputType.NONE);
1244+
}
1245+
12351246
@SuppressWarnings("deprecation") // InputMethodSubtype
12361247
@Test
12371248
public void inputConnection_finishComposingTextUpdatesIMM() throws JSONException {
@@ -1310,7 +1321,7 @@ public void inputConnection_textInputTypeNone() {
13101321
InputConnection connection =
13111322
textInputPlugin.createInputConnection(
13121323
testView, mock(KeyboardManager.class), new EditorInfo());
1313-
assertEquals(connection, null);
1324+
assertNotNull(connection);
13141325
}
13151326

13161327
@Test

0 commit comments

Comments
 (0)