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

Commit ced6c63

Browse files
authored
Request a reattach when creating the text input plugin on Android (#13474)
1 parent 0a8bd9d commit ced6c63

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ public TextInputChannel(@NonNull DartExecutor dartExecutor) {
110110
channel.setMethodCallHandler(parsingMethodHandler);
111111
}
112112

113+
/**
114+
* Instructs Flutter to reattach the last active text input client, if any.
115+
*
116+
* This is necessary when the view heirarchy has been detached and reattached
117+
* to a {@link FlutterEngine}, as the engine may have kept alive a text
118+
* editing client on the Dart side.
119+
*/
120+
public void requestExistingInputState() {
121+
channel.invokeMethod("TextInputClient.requestExistingInputState", null);
122+
}
123+
113124
/**
114125
* Instructs Flutter to update its text input editing state to reflect the given configuration.
115126
*/

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public void clearClient() {
9090
}
9191
});
9292

93+
textInputChannel.requestExistingInputState();
94+
9395
this.platformViewsController = platformViewsController;
9496
this.platformViewsController.attachTextInputPlugin(this);
9597
restartAlwaysRequired = isRestartAlwaysRequired();

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

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

33
import android.content.Context;
4+
import android.content.res.AssetManager;
45
import android.provider.Settings;
56
import android.util.SparseIntArray;
67
import android.view.View;
78
import android.view.inputmethod.InputMethodManager;
89
import android.view.inputmethod.InputMethodSubtype;
910

11+
import java.nio.ByteBuffer;
12+
1013
import org.junit.Test;
1114
import org.junit.runner.RunWith;
1215
import org.robolectric.RobolectricTestRunner;
@@ -18,16 +21,38 @@
1821
import org.robolectric.shadows.ShadowBuild;
1922
import org.robolectric.shadows.ShadowInputMethodManager;
2023

24+
import io.flutter.embedding.engine.FlutterJNI;
2125
import io.flutter.embedding.engine.dart.DartExecutor;
2226
import io.flutter.embedding.engine.systemchannels.TextInputChannel;
27+
import io.flutter.plugin.common.JSONMethodCodec;
28+
import io.flutter.plugin.common.MethodCall;
2329
import io.flutter.plugin.platform.PlatformViewsController;
2430

2531
import static org.junit.Assert.assertEquals;
2632
import static org.mockito.Mockito.mock;
33+
import static org.mockito.Mockito.spy;
34+
import static org.mockito.Mockito.times;
35+
import static org.mockito.Mockito.verify;
2736

2837
@Config(manifest = Config.NONE, shadows = TextInputPluginTest.TestImm.class, sdk = 27)
2938
@RunWith(RobolectricTestRunner.class)
3039
public class TextInputPluginTest {
40+
@Test
41+
public void textInputPlugin_RequestsReattachOnCreation() {
42+
// Initialize a general TextInputPlugin.
43+
InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
44+
TestImm testImm = Shadow.extract(RuntimeEnvironment.application.getSystemService(Context.INPUT_METHOD_SERVICE));
45+
testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
46+
View testView = new View(RuntimeEnvironment.application);
47+
48+
FlutterJNI mockFlutterJni = mock(FlutterJNI.class);
49+
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class)));
50+
TextInputPlugin textInputPlugin = new TextInputPlugin(testView, dartExecutor, mock(PlatformViewsController.class));
51+
52+
ByteBuffer message = JSONMethodCodec.INSTANCE.encodeMethodCall(new MethodCall("TextInputClient.requestExistingInputState", null));
53+
verify(dartExecutor, times(1)).send("flutter/textinput", message, null);
54+
}
55+
3156
@Test
3257
public void setTextInputEditingState_doesNotRestartWhenTextIsIdentical() {
3358
// Initialize a general TextInputPlugin.

0 commit comments

Comments
 (0)