Flutter: Samsung Keyboard duplicates text when restoring composing regions (restart text input, punctuation)

Created on 23 Apr 2019  Β·  139Comments  Β·  Source: flutter/flutter

Hello!

Within a flutter application that has TextField or TextFormField the text can get duplicated upon first time data entry.

When first entering a keypress, within a field that already has text pre-filled, the text duplicates then your keypress is attached.

I am experiencing something that exhibits this behavior on my Samsung Galaxy S7, S8 and S9 (only devices I have to test with). This doesn't occur within the emulator (Galaxy Nexus9 and Pixel 2).

If I place a space at the end of the field, this problem doesn't happen, however, if I tap in middle of a pre filled field (using controller or initialValue) and press a key it does occur.

class SampleTextFormPage extends StatefulWidget {
    @override
    State<StatefulWidget> createState() => new _SampleTextFormPage();
}

class _SampleTextFormPage extends State<SampleTextFormPage> {
    final _scaffoldKey = new GlobalKey<ScaffoldState>();

    TextEditingController _txtController;

    @override
    void initState() {
        super.initState();

        _txtController = TextEditingController(text:'Using Controller');
    }

    @override
    Widget build(BuildContext context) { Scaffold scaffold = new Scaffold(
        key: _scaffoldKey,
        appBar: new AppBar(
            title: new Text('Text Entry',
                style: const TextStyle(
                    color: Colors.white)
            ),
            backgroundColor: Colors.indigo
        ),
        body:  Column(children: [
            //field 1
            TextField(
                 autocorrect: false,
                 autofocus: true,
                 controller: _txtController,
            ),

           //field 2
           TextFormField(
               autocorrect: false,
               autofocus: true,
               initialValue: 'Using initialValue',
           )
        ])
    );

    return scaffold;
    }
}

https://stackoverflow.com/questions/52894507/flutter-texfield-and-textformfield-duplicates-text-when-using-initial-value-or-c

text input crowd device-specific engine material design platform-android

Most helpful comment

Have confirmed text no longer duplicates on punctuation. The change has made it into master channel via https://github.com/flutter/flutter/commit/fbb2f07497868a2b63c23abaa31aed02fc13d057

There is still the second half of the bug where text duplicates when the keyboard is hidden+unhidden+type. This does not pass through the finishComposingText codepath and requires a different workaround.

All 139 comments

Error on any application written flutter. Even on the base with one input field.
Playback error when entering Russian words / letters

Thanks for submitting this. I'm unable to reproduce it on a physical Pixel 2 right now. I think I have an S7 that I can try this on tomorrow. I'll post back with what happens.

Thanks for submitting this. I'm unable to reproduce it on a physical Pixel 2 right now. I think I have an S7 that I can try this on tomorrow. I'll post back with what happens.

I'm testing on galaxy s8 and s9
Reproduced only with Russian letters.
Scenario

  • Enter the word
  • Spacebar
  • Delete twice (one space and one letter will be removed)
  • Enter any letter in Russian

Total: duplicates the entire word + letter

The error is reproduced in Google Ad. Installed with play market

Ok I've got an S6 and I just installed a Russian keyboard, but I don't see the bug using the code that you provided above.

Start your app and delete the existing text:

Type a word in Russian followed by one space:

Press backspace twice:

Type a letter, but I see no duplication:

Take any phone of the galaxy s8 or s9 family.
Install an empty application with one input and try on a standard keyboard with Russian letters.

Tested on two top Samsung s8/s9.

https://www.youtube.com/watch?v=MVR8lW_tYww

Can you try this in a native app and confirm that you don't see this behavior?

I use the standard firmware Samsung Galaxy S8 and Galaxy S9.
All applications that are installed on the phone work fine. Native App, react native, telegram, skype, google and so on.

We encountered this problem at the release stage of our flutter application

Alright I see, thanks for clarifying. I tried again with the S6 but with the default keyboard in Russian and couldn't reproduce it still. I'll try to track down an S8 or S9.

Russian keyboard not required.
Tested this on an Samsung T580.

Create an app with a TextField:

  • Enter a few letters.
  • Press the 'done' button on the keyboard to close it.
  • Click the field again and click a letter.

So if you enter 'La', close, open, and press '!'. The TextField will read "LaLa!".

_This was tested on the dev (1.5.8) and stable (1.2.1) branch._

Note: It is not reproducible on an Samsung S8.
Related SO: https://stackoverflow.com/questions/52894507/flutter-texfield-and-textformfield-duplicates-text-when-using-initial-value-or-c

I found a Samsung T110 and couldn't reproduce it. Hope to try it on an S9 or T580 when I can.

The above issue also reported this same problem on: Samsung Galaxy Tablet 8 A (Android 8.1). A bunch of good reproduction instructions there too. It seems like this definitely has to do with Samsung's predictive text.

The above issue also reported this same problem on: Samsung Galaxy Tablet 8 A (Android 8.1). A bunch of good reproduction instructions there too. It seems like this definitely has to do with Samsung's predictive text.

when to expect a solution to the problem?

This is on my list of things I'd like to fix, though I still haven't come across a device that can reproduce it...

If you or anyone else has some time to work on a PR to fix this in the meantime, please do!

More testing per #33255 showed another interesting behavior @justinmc
I typed in 'abc def' initially. With space in the middle.
Hit done.
Touched the input again, typed 'g'
Edit widget now shows 'abc defdefg'

Wondering if this was looking at the last word, I tried another test case.

Initial text

abc def ghi

Hit Done, touch widget to edit it
Input

j

Edit widget now shows: 'abc def ghighij'

Flutter v1.5.4-hotfix.2,

Stock Keyboard
In agreement with @charlesokt. I tested this on Galaxy S9 and S9 Note. Turning off Samsung Keyboard predictive text does prevent the duplication from occurring.

Initial Text value / removing all text to smaller caret size
If you create a new textfield/textFormField with no initial text value set, the issue doesn't seem to manifest. However, when the initial values are set it will occur. If you have an initial value and press the delete key to 'completely' remove all text, you will notice the Caret size will go from a larger size to a smaller size. When it reaches the smaller size, the duplication issue will not occur even though you have set the initial text value.

Potential related issue
I ran across this discussion that seems pertinent to this bug. Notice the discussion on duplicated text, predictive text, etc.

https://github.com/flutter/flutter/issues/22828

Help solve the problem! Our release is delayed because of this.

Here is a similar problem #19743
A year has passed ..

To add another affected device to the list, this issue was seen in https://github.com/flutter/flutter/issues/19743 on a Galaxy Grand Prime with Android 5.1.1.

I can't make promises, but I compiled the flutter engine and will attempt to diagnose and/or fix this.

Below is more full logs of what I'm seeing with a debug build of the engine running my test scenario as detailed in #33255. I did a print statement for when the text edit controller receives the message that text has changed, so you'll see a "new text -> " log entry when the controller is called from my TextEdit. For this test, I did the following:

  1. touched the TextEdit
  2. hit 'a', done
  3. touched TextEdit again
  4. hit 'd'.
  5. TextEdit widget now shows 'aad'.

For sake of completeness, this issue seems to only affect Samsung devices and turning off Predictive Text on the device seems to avoid the issue.

The test here was done against SM-T380, Samsung Galaxy Note 8A, Android 8.1.1 using the current Beta 1.6.3.
Framework: bc7bc94083
Engine: 8dc3a4cde2

Debug logs for anyone else so inclined and interested:

06-10 19:02:23.050 5555 5584 I flutter : new text -> a
06-10 19:02:23.051 1566 1566 V Surface : sf_framedrop debug : 0x4f4c, game : false, logging : 0
06-10 19:02:23.051 1566 1566 D ViewRootImpl@6844e5e[InputMethod]: Relayout returned: old=[0,542][800,1280] new=[0,542][800,1280] result=0x7 surface={valid=true 2333847552} changed=true
06-10 19:02:23.053 1566 4806 W Adreno-EGL: : EGL_BAD_ATTRIBUTE
06-10 19:02:23.058 1566 4806 D vndksupport: Loading /vendor/lib/hw/gralloc.msm8937.so from current namespace instead of sphal namespace.
06-10 19:02:23.059 1566 4806 D OpenGLRenderer: eglCreateWindowSurface = 0xac813f48, 0x8b1bb008
06-10 19:02:23.062 1566 1566 I SKBD : azs getNavigationBarHeight() first use took : 1
06-10 19:02:23.071 1566 1566 V InputMethodManager: Not IME target window, ignoring
06-10 19:02:23.072 1566 1566 I chatty : uid=10126(com.sec.android.inputmethod) identical 3 lines
06-10 19:02:23.072 1566 1566 V InputMethodManager: Not IME target window, ignoring
06-10 19:02:23.073 1566 1566 I SKBD : ToolBarContainer [PF_OP][updateToolBarPage] 5126562
06-10 19:02:23.141 1566 1566 I SKBD : AbstractKeyboardView drawAllKey nanoTime= 55282031, isOrientationLandscape() = false
06-10 19:02:23.141 1566 1566 I SKBD_Performance: AbstractKeyboardView [PF_OP] onDraw 57409948
06-10 19:02:23.142 1566 1566 I SKBD_Performance: AbstractKeyboardView [PF_OP] onDraw 44687
06-10 19:02:23.150 1094 1121 D WindowManager: finishDrawingWindow: Window{d04c601 u0 InputMethod} mDrawState=DRAW_PENDING
06-10 19:02:23.155 1571 16310 D PipManager: onImeVisibilityChanged - imeVisible : true imeHeight:0
06-10 19:02:23.155 1571 16310 D PipManager: onMovementBoundsChanged
06-10 19:02:23.160 1566 1566 I SKBD : alf [PF_KL][SIIC] getSelectedText done 6
06-10 19:02:23.160 1566 1566 E SKBD : bbd [USICM][getSelectedText] updated, but null is returned
06-10 19:02:23.162 1566 1566 I SKBD : alf [PF_KL][SIIC] getTextBeforeCursor[ 127 ] done 2
06-10 19:02:23.165 1566 1566 I SKBD : alf [PF_KL][SIIC] getTextAfterCursor[ 127 ] done 2
06-10 19:02:23.166 1566 1566 I SKBD_Performance: [IIManager] [PF_KL] IIfo BuildTime - tookTime : 0
06-10 19:02:23.168 1571 1908 D PipManager: onImeVisibilityChanged - imeVisible : true imeHeight:494
06-10 19:02:23.168 1571 1908 D PipManager: onMovementBoundsChanged
06-10 19:02:23.169 5555 5555 D ViewRootImpl@e872005[MainActivity]: MSG_RESIZED: frame=Rect(0, 0 - 800, 1280) ci=Rect(0, 32 - 0, 494) vi=Rect(0, 32 - 0, 494) or=1
06-10 19:02:23.171 1566 1566 I SKBD : azw getNetworkState : 2
06-10 19:02:23.172 1566 1566 I SKBD_Performance: [IIManager] [PF_KL] IIfo BuildTime - tookTime : 0
06-10 19:02:23.181 1094 6754 V WindowManager: Relayout Window{59011d4 u0 com.keyotech.testflutter/com.keyotech.testflutter.MainActivity}: viewVisibility=0 req=800x1280 WM.LayoutParams{(0,0)(fillxfill) sim=110 ty=1 fl=#81810100 pfl=0x20000 fmt=-3 wanim=0x1030001 vsysui=0x700 needsMenuKey=2 colorMode=0 naviIconColor=0}
06-10 19:02:23.196 5555 5555 D ViewRootImpl@e872005[MainActivity]: Relayout returned: old=[0,0][800,1280] new=[0,0][800,1280] result=0x1 surface={valid=true 2382137344} changed=false
06-10 19:02:23.197 479 479 I SurfaceFlinger: Display 0 HWC layers:
06-10 19:02:23.197 479 479 I SurfaceFlinger: type | handle | flag | format | source crop (l,t,r,b) | frame | name
06-10 19:02:23.197 479 479 I SurfaceFlinger: ------------+--------------+------+-----------+----------------------------+---------------------+------
06-10 19:02:23.197 479 479 I SurfaceFlinger: Device | 0xa90a9100 | 0002 | RGBA_8888 | 0.0 0.0 800.0 1280.0 | 0 0 800 1280 | SurfaceView - com.keyotech.testflutt[...]utter.MainActivity@c5eb781@0[5555]#0
06-10 19:02:23.197 479 479 I SurfaceFlinger: Device | 0xa90a9400 | 0000 | RGBA_8888 | 0.0 0.0 800.0 32.0 | 0 0 800 32 | com.keyotech.testflutter/com.keyotech.testflutter.MainActivity[5555]#0
06-10 19:02:23.197 479 479 I SurfaceFlinger: Device | 0xa90a9080 | 0000 | RGBA_8888 | 0.0 0.0 800.0 631.0 | 0 649 800 1280 | InputMethod[1566]#0
06-10 19:02:23.197 479 479 I SurfaceFlinger: Device | 0xa90a9480 | 0000 | RGBA_8888 | 0.0 0.0 800.0 32.0 | 0 0 800 32 | StatusBar[1571]#0
06-10 19:02:23.197 479 479 I SurfaceFlinger:
06-10 19:02:23.260 1094 1651 E Watchdog: @Sync 29140 [2019-06-10 19:02:23.260]
06-10 19:02:23.319 1094 1121 D CustomFrequencyManagerService: releaseDVFSLockLocked : Getting Lock type frm List : DVFS_MIN_LIMIT frequency : 1094400 uid : 1000 pid : 1094 tag : com.sec.android.inputmethod@35
06-10 19:02:23.797 1824 1824 D io_stats: !@ 179,0 r 554029 22731934 w 1087505 19387128 d 87448 30637640 f 326046 326037 iot 2055220 2348326 th 51200 0 0 pt 0 inp 0 0 874428.354
06-10 19:02:28.803 1824 1824 D io_stats: !@ 179,0 r 554029 22731934 w 1087515 19387260 d 87449 30637676 f 326047 326038 iot 2055220 2348340 th 51200 0 0 pt 0 inp 0 0 874433.360
06-10 19:02:29.163 683 30287 V APM_AudioPolicyManager: getAudioPolicyConfig: audioParam;outDevice
06-10 19:02:29.163 683 30287 V APM_AudioPolicyManager: getNewOutputDevice() selected device 0
06-10 19:02:29.163 683 30287 V APM_AudioPolicyManager: ### curdevice : 2
06-10 19:02:29.163 1094 4176 D SSRM:i : AudioType = 2, Vol = 0
06-10 19:02:29.271 1094 4176 D TelephonyManager: getAllCellInfo : Caller (PID / UID / TID): 1094 / 1000 / 4176
06-10 19:02:29.291 1094 4176 D SSRM:c : SIOP:: AP:327(331,0) BAT:322(322,0) CHG:0(0,0) ATC:0(0,0)
06-10 19:02:32.115 1094 1147 V MARsPolicyManager: updateFromMARsThread
06-10 19:02:32.116 1094 1148 D MARsDBManager: updatePkgsToSMDB : begin --size 1
06-10 19:02:32.132 1094 1148 D MARsDBManager: updatePkgsToSMDB : end
06-10 19:02:32.132 1094 1148 D MARsDBManager: onChange - mSmartManagerObserver! Uri = content://com.samsung.android.sm/AppFreezer?MARs-self=true&MARs=true
06-10 19:02:32.287 1094 1257 D SensorService: [SO] 0.002 0.145 10.047
06-10 19:02:33.808 1824 1824 D io_stats: !@ 179,0 r 554030 22731938 w 1087527 19387308 d 87449 30637676 f 326047 326038 iot 2055220 2348347 th 51200 0 0 pt 0 inp 0 0 874438.364
06-10 19:02:38.813 1824 1824 D io_stats: !@ 179,0 r 554030 22731938 w 1087531 19387336 d 87449 30637676 f 326048 326039 iot 2055220 2348353 th 51200 0 0 pt 0 inp 0 0 874443.369
06-10 19:02:39.302 683 30287 V APM_AudioPolicyManager: getAudioPolicyConfig: audioParam;outDevice
06-10 19:02:39.302 683 30287 V APM_AudioPolicyManager: getNewOutputDevice() selected device 0
06-10 19:02:39.302 683 30287 V APM_AudioPolicyManager: ### curdevice : 2
06-10 19:02:39.302 1094 4176 D SSRM:i : AudioType = 2, Vol = 0
06-10 19:02:39.324 1094 4176 D SSRM:c : SIOP:: AP:327(330,0) BAT:322(322,0) CHG:0(0,0) ATC:0(0,0)
06-10 19:02:39.577 1094 1378 D WifiTrafficPoller: TrafficStats TxPkts=145921 RxPkts=212115 TxBytes=49347685 RxBytes=191056925 , Foreground uid=10157 pkgName=com.keyotech.testflutter txBytes=90328121 rxBytes=1114885
06-10 19:02:39.799 1094 6592 D BatteryService: !@BatteryListener : batteryPropertiesChanged!
06-10 19:02:40.024 1094 1291 D InputReader: Input event(5): value=1 when=874444581494000
06-10 19:02:40.024 1094 1291 D InputReader: Input event(5): value=1 when=874444581494000
06-10 19:02:40.024 1094 1291 I InputReader: Touch event's action is 0x0 (deviceType=0) [pCnt=1, s=0.789 ] when=874444581494000
06-10 19:02:40.024 1094 1290 I InputDispatcher: Delivering touch to (1571): action: 0x4, toolType: 1
06-10 19:02:40.024 1094 1290 I InputDispatcher: Delivering touch to (1566): action: 0x0, toolType: 1
06-10 19:02:40.025 1566 1566 D ViewRootImpl@6844e5e[InputMethod]: ViewPostIme pointer 0
06-10 19:02:40.027 1094 1290 D PowerManagerService: [api] userActivityFromNative : 10 (event: 2 flags: 0) eventTime = 874444581
06-10 19:02:40.029 1566 1566 E SKBDC : SSLanguageModelManager buildContextualCLM()::Word Probability is zero
06-10 19:02:40.029 1566 1566 I SKBD : bnd [PF_KL][getKeyIndexAndNearbyCodes] 411822, In Tyme, getSimpleKeyIndexAndNearbyCodes
06-10 19:02:40.033 1566 1566 I SKBD_Performance: AbstractKeyboardView [PF_KL] onTouchEvent 0 5 4 4875312
06-10 19:02:40.034 1566 1566 I SKBD_Performance: AbstractKeyboardView [PF_OP] onDraw 36302
06-10 19:02:40.064 1094 1291 D InputReader: Input event(5): value=0 when=874444621591000
06-10 19:02:40.064 1094 1291 D InputReader: Input event(5): value=0 when=874444621591000
06-10 19:02:40.064 1094 1291 I InputReader: Touch event's action is 0x1 (deviceType=0) [pCnt=1, s=] when=874444621591000
06-10 19:02:40.064 1094 1290 I InputDispatcher: Delivering touch to (1566): action: 0x1, toolType: 1
06-10 19:02:40.065 1566 1566 D ViewRootImpl@6844e5e[InputMethod]: ViewPostIme pointer 1
06-10 19:02:40.071 1566 1566 I SKBD : alf [PF_KL][SIIC] getTextBeforeCursor[ 2 ] done 1
06-10 19:02:40.072 1566 1566 I SKBD : alf [PF_KL][SIIC] getTextBeforeCursor[ 127 ] done 1
06-10 19:02:40.073 1566 1566 I SKBD : alf [PF_KL][SIIC] getTextAfterCursor[ 127 ] done 1
06-10 19:02:40.074 1566 1566 I SKBD_Performance: [IIManager] [PF_KL] IIfo BuildTime - tookTime : 0
06-10 19:02:40.077 1566 1566 I SKBD : alf [PF_KL][SIIC] getExtractedText done 2
06-10 19:02:40.079 5555 5555 E SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
06-10 19:02:40.079 5555 5555 E SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
06-10 19:02:40.079 1566 1566 I SKBD : [IIManager] IIfo SI [il:0x656e4742] [p:1] [c:1] [t:1] [im:0/0/0/0/0/0] [sC:0] [aC:1] [sS:0] [aS:1] [aP:1] [pW:0] [eM:0] [uR:0] [acI:0] [iT:8001] [iO:2000006] [pID:5555] [pO:null]
06-10 19:02:40.079 1566 1566 I SKBD : [IIManager] IIfo II [ir:0] [rand:b8d870a07e094cc9a48dc5687ec7e6d8] [hC:0] [hI:0] [tr:0] [tc:1] [long:0] [cpl:2] [xyD:0/-2] [xycD:-14/-11] [kWHG:63/75/8] [tD:40] [tP:13] [fil:true] [IC:9/20] [cB:6/1]
06-10 19:02:40.080 1566 1566 I SKBD : alf [SIIC] setComposingText : true , 1
06-10 19:02:40.080 1566 1566 I SKBD : [ATIM] [PF_KL][onCharacterKey] 11
06-10 19:02:40.080 1566 1566 I SKBD : apf [PF_KL][onKeyHandleNormalKey::onCharacterKey] 11564479
06-10 19:02:40.080 1566 1566 I SKBD : ako [PF_KL][onKey] 12110468
06-10 19:02:40.081 1566 1566 I SKBD_Performance: AbstractKeyboardView [PF_KL] onTouchEvent 1 2 15 15242968
06-10 19:02:40.081 1566 1566 I SKBD_Performance: AbstractKeyboardView [PF_OP] onDraw 25365
06-10 19:02:40.099 1566 1566 I SKBD : [ATIM] [updateSelectionForInputModule] oldSelStart : 1, oldSelEnd : 1, newSelStart : 3, newSelEnd : 3, candidatesStart : 1, candidatesEnd : 3, viewClicked : false
06-10 19:02:40.099 1566 1566 I SKBD : [ATIM] [updateSelectionForInputModule] isTyping : true, viewClicked : false, isKBDShown : true
> 06-10 19:02:40.104 5555 5584 I flutter : new text -> aad
06-10 19:02:40.128 1566 1566 E SKBD : bbl Dismiss keyPreviewView is null

If you wanted to explore our android text input handling, you can take a look at shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java and TextInputPlugin.java

I could imaging the Samsung predictive text is using the android's text API/callbacks strangely or in an unintended way, causing us to misinterpret predicted words or parts of predicted words as additional input. Nonetheless, we should still find a way to support Samsung keyboards without negatively impacting other platforms.

So, here's what I've found so far on my affected Samsung device.
My test case:
1) Touch TextEdit
2) 'abc def'
3) Hit Done
4) 'g'
5) Widget shows 'abd defdefg'

I've been using a build of the engine to help track down what is happening here and I think I've pinpointed the right area.

InputConnectionAdaptor, when calling updateEditingState() seems to be reporting the wrong information on the Samsung device - as opposed to my Pixel 3.

Pixel 3 (which works correctly), during the abc def test:

mImm.updateSelection(mFlutterView,
selectionStart, selectionEnd,
composingStart, composingEnd);

selectionStart is = 7
selectionEnd is = 7
composingStart is = 4
composingEnd is = 7

Upon hitting g:

mImm.updateSelection is sent the following parameters:

selectionStart is = 8
selectionEnd is = 8
composingStart is = 4
composingEnd is = 8

Results in the correct "abc defg"

On my affected Samsung Device, doing this same test 'abc def' is input:

mImm.updateSelection is sent the following parameters:

selectionStart is = 7
selectionEnd is = 7
composingStart is = -1
composingEnd is = -1

Upon hitting g:

selectionStart is = 11
selectionEnd is = 11
composingStart is = 7
composingEnd is = 11

And results in the duplicated text: 'abc defdefg'

So, I imagine this has to do with the composing start and end being fed negative numbers. Will continue to troubleshoot, but that's where I am so far.

I'm currently testing some workaround code and thought I'd share more findings for interested parties.

On my affected Samsung device beginBatchEdit is apparently called twice whenever an Editable is modified. Unfortunately, the first call in to Samsung's implementation of that method results in Log.e with message "SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length". While this may or may not be important, what is important is that this error indicates prevention of whatever other logic is supposed to happen and results in a composing start and end index value of -1 to come back, worse, the Editable's internal CharSequence has now set duplicated text inside of it. I think what is happening is the current Span is not being removed, and instead the new span, which is supposed to replace it, is just being appended...?

So, back in flutter-land, when InputConnectionAdaptor.java calls updateEditingState, we can't trust the .toString() method to return the expected string from the Editable as we send this over to textInputChannel.updateEditingState.

My workaround, which is very much a work in progress and needs more testing, is to manually correct the word/span and replace it with the composingText string that is being edited based on cursor positions in the underlying Editable. Initial work here indicates this works so far, at least on my Samsung device, I also manually correct the composing start and end index (because who knows what else that may affect).

I guess this leaves open a couple of questions. First, is what I'm working around a bug or a feature in Saumsung's implementation (I'm leaning towards bug)... and probably more importantly, even if Samsung fixes this, it's pretty likely this will never be fixed in a large majority of devices that are affected by it.

Suffice to say, I'm 99% sure this is not a Flutter issue, but rather a manufacturer Android implementation issue. I think we can work around it, though, I'm not sure to what extent Flutter is supposed to work around things like this? Of course, this is assuming I correctly understand most/all there is to know with how Flutter interacts with the Input methods and channels of Android correctly; I may have missed something in regards to how we're interacting with the underlying Editable, though, I'm fairly confident in what I've seen so far.

Regardless, I'll make a work around and get it tested on both Samsung and non-Samsung devices - sharing all the results of course.

@GaryQian, have any other insights here?

Thanks for all your work on this. It is indeed a gray area when dealing with hacks to fix specific device bugs. Namely, if the device itself fixes the bug, would we still handle it properly? And in terms of code hygiene, filling our codebase with hacks makes it very unmaintainable and can incur performance hits over time.

Do you think it is possible for you to get your fix/workaround for this in a plugin form? It would be phenomenal if people could simply install a Samsung keyboard fix plugin that would fix this.

Really appreciate your exploration of this topic!

I agree with what you say Gary. Though, it somewhat begs the question, which Samsung devices are affected by this, and which are not? I mean, there could be quite a prevalence issue here that may need to be weighed carefully. As I understand it, Samsung devices are quite popular in the Android space and people trying to deploy Flutter apps seeing this weird behavior may get the wrong idea.

Regardless, I'll formalize my workaround on the engine for review so you guys can better see what's involved.

I could probably look at making a plugin, though I'm not totally sure how I would override the functionality found in InputConnectionAdaptor? As it stands right now, I'm adding one new function that overrides the standard behavior in updateEditingState that seems to be working for both Samsung and non-Samsung devices. I need more testing, but what I have is quite promising -- albeit not super elegant and kind of ugly.

I have a galaxy s8 and galaxy s9 on hand
I think this is the problem of all new Samsung operating systems. At the moment, our metrics show the wide distribution of Samsung among users. This is an important platform.

Help please solve this problem. Our programmers can not cope with it (

Yeah, due to the market share of Samsung devices, if this cannot be applied at engine level, It may be reasonable to go ahead and apply a fix as long as it is compatible with both Samsung's bug and correct versions.

I'll gather some opinions on this when you post your PR!

So, I was testing my work around... it's looking pretty good, but, the changes needed are probably not what you'd want to apply at the engine level; as mentioned, we'll probably take on technical debt by doing this.

Options? Well, I'm working instead now on bringing in part of the Android source code for Editable and SpannableStringBuilder, making some changes in that, then incorporating that in to the engine instead. The idea is to locally patch up, so to speak, the broken parts and use the patched up versions for what Flutter is already expecting. I know when I made a small game engine many years ago that spanned iOS, Android, Windows, etc, I had to do similar things as I couldn't trust certain platforms half the time to do what they were supposed to do (Android was very guilty of this, though, thankfully, it doesn't seem AS bad today as it was back then).

I haven't gotten far on this yet as I got tripped up by something trivial -- how to add new .java files to the ninja build scripts? I keep getting package not found errors for my new java files. I put the files in the same location as the referencing files and put them in the same package, so they should be visible -- though, maybe, my files aren't being compiled in?

@GaryQian @justinmc ? Any pointers here?

I would think that should work for adding a new java file... Hopefully @GaryQian has some tips :)

Have you taken a look at shell/platform/android/BUILD.gn?

We typically include the files in the various BUILD.gn files scattered about.

Ok thanks @GaryQian. I'm still new to how ninja works; I'm still coming from back in the day makefiles and what not. I'll get this going and present findings, solutions, and a PR soon.

Not sure if it helps, but for me the following workaround fixed the issue with text duplication on Samsung S8:

    override fun createFlutterView(context: Context?): FlutterView {
        val flutterView = object: FlutterView(this, null, createFlutterNativeView()) {

            override fun onCreateInputConnection(outAttrs: EditorInfo?): InputConnection? {
                val connection = super.onCreateInputConnection(outAttrs)

                outAttrs?.apply {
                    var type = InputType.TYPE_CLASS_TEXT               or
                               InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS or
                               InputType.TYPE_TEXT_VARIATION_PASSWORD

                    if ((inputType and InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0) {
                        type = type or InputType.TYPE_TEXT_FLAG_MULTI_LINE
                    }

                    if ((inputType and InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
                        type = type or InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
                    }

                    if ((inputType and InputType.TYPE_TEXT_FLAG_CAP_WORDS) != 0) {
                        type = type or InputType.TYPE_TEXT_FLAG_CAP_WORDS
                    }

                    if ((inputType and InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) != 0) {
                        type = type or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
                    }

                    inputType = type
                }

                return connection
            }

        }

        setContentView(flutterView, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))

        return flutterView
    }

This code must be added into main activity

Thanks for the comment @33-Elephants but it looks like you're programmatically forcing TYPE_TEXT_FLAG_NO_SUGGESTIONS for all inputs (which would affect all devices, not just samsung). It's been discussed earlier and elsewhere that manually turning off predictive text on the affected Samsung devices sidesteps the problem. Your solution looks to be doing this without having the user turn this off manually, but, it would also effectively turn off suggestions/predictive text for all users of your app, regardless of device, with no way for them to turn it on.

As for me, I got pulled away to work on higher priority issues for a while with my own flutter apps. Last I was working on this, it came down to pulling in Android OS source code for SpannableStringBuilder (and its dependencies), writing custom code over this, and trying to test fixes at this level -- as expected, this is much more complicated than I originally thought.

All in all, it looks like (but not totally proven) the affected samsung devices has some sort of faulty implementation of SpannableStringBuilder from AOS.

So, I have a workaround where I manually correct spannable strings when the text gets to the input widget... but I think the "right", but much harder, answer is to manually override the faulty AOS implementation... this is not as small of a task as I'd hoped.

I've finally gotten brave enough to look at FlutterJNI because that's where this is going.
@matthew-carroll if you have any pointers for how best to use FlutterJNI in regards to implementing ArrayUtils / unpaddedarray (among other features seemingly mostly found in android.internal.util.*)... all that stuff are dependencies from SpannableStringBuilder... and if I'm rolling a custom implementation...

@charlesokt can you describe the kinds of changes you're trying to make to FlutterJNI? It should be exceedingly rare that any changes are needed for that interface, especially when it comes to adjusting text input behavior. I would expect any such adjustments to occur in TextInputPlugin and InputConnectionAdapter.

@charlesokt can you describe the kinds of changes you're trying to make to FlutterJNI? It should be exceedingly rare that any changes are needed for that interface, especially when it comes to adjusting text input behavior. I would expect any such adjustments to occur in TextInputPlugin and InputConnectionAdapter.

You'll have to forgive my general ignorance on all of this... what started as a "should be easy to look at" issue has gone well beyond my initial assumptions... I'm just barely getting started with learning anything about the framework and the engine and never even looked at the engine code before all this, I think I did a deep dive in to the middle of the ocean. Here's the general short version of what's going on:

You're definitely right, FlutterJNI is not something that should be changed; I found my way there trying to answer the question of how I could bring in custom c/c++ code in to the engine, specifically to replace or augment android.internal.util. methods and functions. Why? Because the affected Samsung devices per this issue (and linked issues), SpannableStringBuilder is throwing internal errors when text is entered in to an Text Input widget, resulting in TextInputPlugin and/or InputConnectionAdapter receiving and processing incorrect values as becoming part of the Editable object... I think what has happened is while parsing a SpannableString, the afflicted devices error out in the middle of processing, leaving the internal state only half-processed, then the rest of flutter is using bad input.

More specifically: TextInputPlugin.java has a private method setTextInputClient where the object mEditable is instantiated, unfortunately, it is this object that depends on SpannableStringBuilder and is the source of the woes in this issue... so, I have to entertain the idea that these devices have a faulty implementation of the Android source... and the odds of Samsung rolling a patch, and applying it to all affected devices are probably slim... given the prevalence of this manufacturer's deployment rate, it's a good chance this bug will affect Flutter apps for some time.

So, here we are, I have to entertain the idea of making a custom Editable class for TextInputPlugin using a custom/reliable SpannableStringBuilder which depends on ArrayUtils and other things... the stock classes rely heavily on android.internal.util functions, mostly for array manipulation, but I can't seem to get to those things as it is, and of course, most of this stuff is private, and in java, I can't inherit/override these without writing my own custom code to replace them in the first place...

I'm looking for guidance for a couple of things:

1) Does the flutter engine already expose similar functionality to android.internal.util - I'd imagine a lot of this would be JNI/NDK c/c++ code dealing with memory ops.

2) How would I go about adding new native code in to the engine in support of my new custom SpannableStringBuilder / ArrayUtils java class. I'm not afraid of C/C++ or using JNI, but I'm not sure the location of where to start adding this type of code. What are the rules and etiquette in this area, I'd imagine we probably don't want to just start adding in new c files to some random directory and haphazardly try to start running it.

Yes, I could probably make suitable java code to handle a custom ArrayUtils... but considering the stock Android source is calling down to native itself, I'd imagine the performance indicators would be less than ideal. The Right Way is probably going custom native as well.

I'll defer to @jason-simmons and @chinmaygarde with regard to adding C++ code.

I would also encourage you to investigate every Java-based solution before venturing into C++ territory.

CC @gspencergoog for deeper knowledge about text input.

CC @Hixie for any policy positions related to patching broken behavior in a set of devices under a specific OEM.

Thanks Matthew! I look forward to further guidance, and, I know all you guys are really busy with all things Flutter, so I appreciate taking time away to hand hold this upstart!

If we can make the Samsung devices work while using the protocol correctly, then let's do it (even if it requires some very specific contortions). If we can't, but we can reliably detect the bad behavior and respond appropriately, let's do that. If we can't do that either, it gets more likely that we should just not do anything.

We should definitely not do anything that would lead to bad behavior when the device does everything correctly.

Whatever we do we should make sure to document and test the behavior in detail, so that someone two years from now can understand it and confidently refactor the code without regressions.

Thanks for the insight @Hixie. Here's the workaround code with explanation. I'm of the opinion that creating and maintaining a flutter SpannableStringBuilder is probably the better, long-term way to guarantee consistency across devices; but, where is that line drawn of course. Regardless, here's what I have to handle the incoming, bad input.

InputConnectionAdaptor.java

@Override
    public boolean setComposingText(CharSequence text, int newCursorPosition) {
        boolean result;
        if (text.length() == 0) {
            result = super.commitText(text, newCursorPosition);
        } else {
            result = super.setComposingText(text, newCursorPosition);
        }
        updateEditingStateWithComposingText(text);
        return result;
    }


private void updateEditingStateWithComposingText(CharSequence composedWord) {
        if (composedWord == null) {
            updateEditingState();
            return;
        }

        int selectionStart = Selection.getSelectionStart(mEditable);
        int selectionEnd = Selection.getSelectionEnd(mEditable);

        int composingStart = BaseInputConnection.getComposingSpanStart(mEditable);
        int composingEnd = BaseInputConnection.getComposingSpanEnd(mEditable);

        String editableStr = mEditable.toString();

        int indexWordBoundary = 0;
        for (int i = selectionStart-1; i > 0; --i) {
            if (editableStr.charAt(i) == ' ') {
                indexWordBoundary = i+1;
                break;
            }
        }

        if (composingStart < 0 && composedWord != null)
            composingStart = composedWord.length();
        if (composingEnd < 0)
            composingEnd = selectionStart - composingStart;

        if (composedWord.length() == 0) {
            //do nothing, user may have done auto-complete, in which case the editable already did the replacement
        }
        else {
            mEditable.replace(indexWordBoundary, selectionStart, composedWord); //manually correct the word that's being edited
        }

        composingEnd = mEditable.toString().length();

        mImm.updateSelection(mFlutterView,
                             selectionStart, selectionEnd,
                             composingStart, composingEnd);

        textInputChannel.updateEditingState(
            mClient,
            mEditable.toString(),
            selectionStart,
            selectionEnd,
            composingStart,
            composingEnd
        );
    }

I created a duplicate updateEditingState function that accepts the CharSequence of whatever the composed word is and call it from setComposingText. This is the only place that needs to call this specialized version (all other calls to updateEditingState continue to call the parameter-less version).

Inside the new updateEditingStateWithComposingText function I attempt to figure out where the word boundary is (I assume word boundaries are only found from space characters, so I may need to augment how to detect word boundaries with characters other than spaces). From there, it replaces the word from the detected wordboundary.

Essentially, I cannot trust the incoming charsequence and modify the editable's text manually, based on the incoming word.

This is tested with affected and not-affected devices and works as expected with and without predictive text features turned on. This also works on words in the middle of the input, not just the last word in the text and replaces them in-place.

This is happening with my Galaxy S9. I'm making an email form input and noticed a strange interaction with the '.' and '@' keys.

1) type 'a.b' into text box
2) hit done to collapse keyboard
3) select text box and type '.c'
The result _should be_ 'a.b.c', but instead we get 'a.b.a.b.c'

Heres my code

Widget buildEmailField(){
    return TextFormField(
        keyboardType: TextInputType.emailAddress,
        autocorrect: false,
        decoration: InputDecoration(
            labelText: 'Email Address',
            hintText: '[email protected]'
        ),
        validator: (String value){
            if (!value.contains(emailRegExp)){
                return 'Enter a valid email address.';
            }
            else{
                return null;
            }
        }
    );
}

@charles,

Could you please give a hint how to integrate your solution into a flutter
project. Thanks

On Fri, Jul 19, 2019 at 3:23 PM charles notifications@github.com wrote:

Thanks for the insight @Hixie https://github.com/Hixie. Here's the
workaround code with explanation. I'm of the opinion that creating and
maintaining a flutter SpannableStringBuilder is probably the better,
long-term way to guarantee consistency across devices; but, where is that
line drawn of course. Regardless, here's what I have to handle the
incoming, bad input.

InputConnectionAdaptor.java

@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
boolean result;
if (text.length() == 0) {
result = super.commitText(text, newCursorPosition);
} else {
result = super.setComposingText(text, newCursorPosition);
}
updateEditingStateWithComposingText(text);
return result;
}

private void updateEditingStateWithComposingText(CharSequence composedWord) {
if (composedWord == null) {
updateEditingState();
return;
}

    int selectionStart = Selection.getSelectionStart(mEditable);
    int selectionEnd = Selection.getSelectionEnd(mEditable);

    int composingStart = BaseInputConnection.getComposingSpanStart(mEditable);
    int composingEnd = BaseInputConnection.getComposingSpanEnd(mEditable);

    String editableStr = mEditable.toString();

    int indexWordBoundary = 0;
    for (int i = selectionStart-1; i > 0; --i) {
        if (editableStr.charAt(i) == ' ') {
            indexWordBoundary = i+1;
            break;
        }
    }

    if (composingStart < 0 && composedWord != null)
        composingStart = composedWord.length();
    if (composingEnd < 0)
        composingEnd = selectionStart - composingStart;

    if (composedWord.length() == 0) {
        //do nothing, user may have done auto-complete, in which case the editable already did the replacement
    }
    else {
        mEditable.replace(indexWordBoundary, selectionStart, composedWord); //manually correct the word that's being edited
    }

    composingEnd = mEditable.toString().length();

    mImm.updateSelection(mFlutterView,
                         selectionStart, selectionEnd,
                         composingStart, composingEnd);

    textInputChannel.updateEditingState(
        mClient,
        mEditable.toString(),
        selectionStart,
        selectionEnd,
        composingStart,
        composingEnd
    );
}

I created a duplicate updateEditingState function that accepts the
CharSequence of whatever the composed word is and call it from
setComposingText. This is the only place that needs to call this
specialized version (all other calls to updateEditingState continue to call
the parameter-less version).

Inside the new updateEditingStateWithComposingText function I attempt to
figure out where the word boundary is (I assume word boundaries are only
found from space characters, so I may need to augment how to detect word
boundaries with characters other than spaces). From there, it replaces the
word from the detected wordboundary.

Essentially, I cannot trust the incoming charsequence and modify the
editable's text manually, based on the incoming word.

This is tested with affected and not-affected devices and works as
expected with and without predictive text features turned on. This also
works on words in the middle of the input, not just the last word in the
text and replaces them in-place.

β€”
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/flutter/flutter/issues/31512?email_source=notifications&email_token=ABX6UOP624IXGAHQAVVAO6LQAGW23A5CNFSM4HH53UVKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2LO5KA#issuecomment-513207976,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABX6UONDUGS43PIHOVB4YJ3QAGW23ANCNFSM4HH53UVA
.

Hi @alesido. The solution I described isn't patched in to the engine, so I suppose if you want to use it, you'd need to snag the flutter engine source, apply these changes, and compile your own engine; then use that in your flutter project. You could probably pull from my repo, but I don't have plans to keep my repo up to date with master, so you're probably better off doing it yourself at this time.

I do apologize for not working on this for a while again, I got really busy with my own project work again and other life stuff; I really can only work on this when my own flutter projects that make me money aren't being demanding. When I can get more time, I'd like to pursue more of the native code in the android part of the flutter engine. I'm at a point where I just need to know more about the engine before I'm super confident in a "good" solution to this on-going problem.

Of course, if there are any other ambitious devs out there wanting to give a solution a go, by all means, I've tried to share as much as I've learned so far in this thread.

Also, I think you tagged the wrong charles?

https://github.com/flutter/flutter/issues/29341 Describes a more general case, and I believe I have a rough cause figured out. Now I am looking at the best way to fix it.

I had the same problem with a Samsung Tab s5e. I solved by installing Google keyboard. I know that is not a real solution but at least you can freely test the device.

It is highly likely that https://github.com/flutter/engine/pull/12432 will fix this, though I have not checked directly yet.

I tried to verify but I couldn't reproduce this issue! I tried on an S6 and on a Galaxy Note 9.

That engine fix is not on the master channel yet, but when it is, please post if anyone can confirm if this is still happening or not!

@seritaApp reported detailed reproduction steps at https://github.com/flutter/flutter/issues/41315#issue-498470521. I haven't personally tested the steps but for them this reproduces consistently on all Flutter channels (including master with flutter/engine#12432). I think the Tab S4 may be the important part of testing this.

Tested with flutter gallery app on Samsung Galaxy Tab S4

  1. Begin to type a word
  2. Leave keyboard mode
  3. Refocus and continue typing
    Instead of adding the new characters, the previous word gets repeated again
    Happens even on the gallery app so it's not related to my code.

Edit: I was trying to type "words" here
ezgif-4-241b62f05f83

Since your fix filters explicitly for korean, it may skip cases where it is actually useful, though it is still unconfirmed this bug is the same.

I have just tested this on master and switched to korean in the keyboard settings. The issue still persists.
I also realized it only happens if auto-completion is turned on.

ezgif-4-34131cbd10cf

I just double checked with the exact reproduction steps in https://github.com/flutter/flutter/issues/41315#issue-498470521 on master with the Note 9 and I couldn't reproduce it. I agree it's probably a few specific devices like the Tab S4.

Can you check whether you can reproduce #30656 ? It probably has the same root cause as this.

I have also experienced this on the Galaxy S8 and S9

On Fri, Sep 27, 2019 at 4:34 PM Justin McCandless notifications@github.com
wrote:

I just double checked with the exact reproduction steps in #41315
(comment)
https://github.com/flutter/flutter/issues/41315#issue-498470521 on
master with the Note 9 and I couldn't reproduce it. I agree it's probably a
few specific devices like the Tab S4.

β€”
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/flutter/flutter/issues/31512?email_source=notifications&email_token=ACONGQDRM5KGH3LEZNHBUGLQLZU45A5CNFSM4HH53UVKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD72AR5I#issuecomment-536086773,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACONGQHG4ZJP7BMUJWISZIDQLZU45ANCNFSM4HH53UVA
.

So is anyone working on a fix? If I was an App developer, this would already be a reason not to use flutter. Samsung is a pretty big manufacturer and this bug seems to be on all new devices

As a result of fixing https://github.com/flutter/flutter/issues/29341, we have determined that the root cause is improper usage/integration of the android API by the samsung keyboard itself. Samsung has been notified of the issue, but it is ambiguous if it is possible to ship a fix to existing devices easily.

I will take another look at this later this week to see if we can repro this and come up with additional workarounds/hacks to ensure this doesn't happen. If anyone has more thorough information on what devices repros this, please let us know!

Unlike #29341 I haven't found this bug in any other app, so there is definitely something that Flutter is doing differently.
I tried installing different Samsung keyboards to find out in which version the issue first occurred.
https://www.apkmirror.com/apk/samsung-electronics-co-ltd/samsung-keyboard-neural-beta/
https://www.apkmirror.com/apk/samsung-electronics-co-ltd/samsung-keyboard/
However, I'm only able to install versions that are newer than the default version of my device and since I already have the latest version this wasn't really useful, but maybe someone else has more luck.
P.S: I Also tried to install it on non-Samsung devices, without any luck so far

Edit: The lowest version I was able to install is "Neural Beta 3.2.02.1" released on December 24, 2018. The bug is reproducible there.

I have created a PR to extend the workaround to cover all samsung devices and locales/languages android lollipop and later using the samsung keyboard. This seems to be effective in working around the issue.

https://github.com/flutter/engine/pull/12780

This bug should be temporarily resolved by the workaround. Please let me know if anyone is still experiencing this!

Just did a flutter upgrade on master channel. Text duplication is still an issue as described in this thread. Tested on Galaxy Tab 8A (SM T380). @GaryQian

flutter doctor -v

[√] Flutter (Channel master, v1.10.12-pre.7, on Microsoft Windows [Version 10.0.18362.356], locale en-US)
β€’ Flutter version 1.10.12-pre.7 at c:dev\fluttersdk\flutter
β€’ Framework revision 71497367ef (3 hours ago), 2019-10-04 16:13:43 -0400
β€’ Engine revision 7d90779bb6
β€’ Dart version 2.6.0 (build 2.6.0-dev.5.0 d6c6d12ebf)

I think the change hasn't been rolled to master yet. I switched to version 1d62160fdb manually, but it's still not fixed

[βœ“] Flutter (Channel master, v1.10.12-pre.5, on Linux, locale de_DE.UTF-8)

[βœ“] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
[βœ“] Android Studio (version 3.5)
[!] IntelliJ IDEA Community Edition (version 2019.2)
    βœ— Flutter plugin not installed; this adds Flutter specific functionality.
    βœ— Dart plugin not installed; this adds Dart specific functionality.
[βœ“] Connected device (1 available)

! Doctor found issues in 1 category.
[jofu@jofu-pc flutter_gallery]$ flutter doctor -v
[βœ“] Flutter (Channel master, v1.10.12-pre.5, on Linux, locale de_DE.UTF-8)
    β€’ Flutter version 1.10.12-pre.5 at /opt/flutter
    β€’ Framework revision 3024053c82 (vor 6 Stunden), 2019-10-04 12:13:36 -0700
    β€’ Engine revision 1d62160fdb
    β€’ Dart version 2.6.0 (build 2.6.0-dev.5.0 7a7dcd1ed9)

[βœ“] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    β€’ Android SDK at /home/jofu/Android/Sdk
    β€’ Android NDK location not configured (optional; useful for native profiling support)
    β€’ Platform android-28, build-tools 28.0.3
    β€’ Java binary at: /opt/android-studio/jre/bin/java
    β€’ Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    β€’ All Android licenses accepted.

[βœ“] Android Studio (version 3.5)
    β€’ Android Studio at /opt/android-studio
    β€’ Flutter plugin version 39.0.3
    β€’ Dart plugin version 191.8423
    β€’ Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[!] IntelliJ IDEA Community Edition (version 2019.2)
    β€’ IntelliJ at /usr/share/idea
    βœ— Flutter plugin not installed; this adds Flutter specific functionality.
    βœ— Dart plugin not installed; this adds Dart specific functionality.
    β€’ For information about installing plugins, see
      https://flutter.dev/intellij-setup/#installing-the-plugins

[βœ“] Connected device (1 available)
    β€’ SM T835 β€’ ce03182369165611017e β€’ android-arm64 β€’ Android 9 (API 28)

! Doctor found issues in 1 category.

@GaryQian Maybe this should be re-opened

Try now. The change only just rolled into master https://github.com/flutter/flutter/commit/43a6626c0c222e55c1d44180c5bceb947e828329
as of about 1 hour ago (~Oct 7 10am PST)

If it is still reproducing, can you please let me know the exact configuration/device/OS/keyboard/procedure you are seeing this on? I was unable to repro this anymore on my devices, but it could still impact others.

Just did a master channel upgrade, text duplication still happens. You may wish to cross reference my related other thread as that's the test I re-ran after upgrading (https://github.com/flutter/flutter/issues/33255).

[√] Flutter (Channel master, v1.10.13-pre.19, on Microsoft Windows [Version 10.0.18362.356], locale en-US)
β€’ Flutter version 1.10.13-pre.19 at c:dev\fluttersdk\flutter
β€’ Framework revision 2d642e95e1 (64 minutes ago), 2019-10-07 11:02:29 -0700
β€’ Engine revision 1d62160fdb
β€’ Dart version 2.6.0 (build 2.6.0-dev.5.0 d6c6d12ebf)

Tested on Original Device:

Galaxy Tab 8A (2017)
Model Number: SM-T380
Android OS: 8.1.0
Kernel Version: 3.18.71-15756985 (Tue Apr 2 2019)
Build Number: M1AJQ.T380DXU3BSD1
Security Release: Apr-2019
Using stock Samsung Keyboard (not sure how to check it's version)

I updated the device and the issue still exists on this as well. Updated device information:

Galaxy Tab 8A (2017)
Model Number: SM-T380
Android OS: 9
One UI Version: 1.1
Kernel Version: 3.18.120-16521006 (Sat Aug 24 2019)
Build Number: PPR1.180610.011.T380DXU3CSHC
Security Release: Jun-2019
Samsung Keyboard version 3.3.31.14

[βœ“] Flutter (Channel master, v1.10.14-pre.12, on Linux, locale de_DE.UTF-8)
    β€’ Flutter version 1.10.14-pre.12 at /opt/flutter
    β€’ Framework revision cdc2d9901d (5 hours ago), 2019-10-07 16:43:04 -0700
    β€’ Engine revision 1d62160fdb
    β€’ Dart version 2.6.0 (build 2.6.0-dev.5.0 d6c6d12ebf)
Galaxy Tab S4
Model Number: SM-T835
Android OS: 9
One UI Version: 1.1
Kernel Version: 4.4.153-16555495
Build Number: PPR1.180610.011.T835XXU3BSG4
Security Release: Jul-2019
Samsung Keyboard version 3.3.21.24

Procedure:

  • Make sure auto-completion is enabled in the keyboard settings
  • Focus on textfield and type a letter (normal letter, not a digit)
  • Unfocus textfield by pressing back (the keyboard needs to disappear, focusing a different textfield won't repro the issue)
  • Focus on the original text again, continue typing

First of all, thank you for investigating and trying to fix this issue.

I just tested it as well on a Galaxy Tab A (SM-T510). As the others reported, the issue is unfortunately still not fixed.

I want to point out that on my device, I do not have to focus-unfocus-focus the text field. The issue is present on initial focus and input.

Here is a video of me trying to input [email protected] into a login form:

As you can see, the duplication happens only after entering something following @ or ..

The TextFormField has autocorrect: false.

The issue is not present if _Smart typing > Predictive text_ has been disabled in the keyboard settings.

More info:

Galaxy Tab A (2019)
Model Number: SM-T510
Android OS: 9
One UI Version: 1.0
Kernel Version: 4.4.111-15874928
Build Number: PPR1.180610.011.T510XXU1ASEF
Security Release: May-2019
Samsung Keyboard version 3.3.30.68
Device Language: German

I've also tested it with a Galaxy A5 (2017) phone, where the issue is not present.

Thanks @Endebert , your test also triggers on my Galaxy Tab 8A. The crux of the problem goes back to what I mentioned earlier, buried in the comments above, that it seems ANY text "word boundary" triggers the glitch. I guess in this case, @ and . are also word boundaries, of sorts (that aren't actual whitespace).

Opening and closing the keyboard also triggers it. The root problem (or one of the root problems) might be that the Samsung keyboard can't read the text of the textfield under certain circumstances.I think this can best be seen in #30656 where normally the handwriting area should contain the text ("Test") but it's just empty.
In case of the auto-completion the keyboard tries to read the text after certain special characters but it just gets an empty string and thus thinks the textfield is empty and just adds the entire suggested string again

Related issue, possible root issue/cause: https://github.com/flutter/flutter/issues/41990

I suspect the bug I fixed with the earlier patch was actually slightly different than the one being reported here. In any case, I'll try to repro this exact bug this time.

We currently lack the above listed devices able to repro this. I have placed orders for the hardware needed to repro, and will update a bit later this week with additional info!

We experience this issue too. Tested on S9 & S10 with Samsung Keyboard. Tested with Swedish and English.

Reproduce:

β€’ On Samsung S9 or S10 (the ones we tested) set Swedish as device language, use Samsung Keyboard, turn on Predictive Text in Samsung Keyboard settings.
β€’ Open a Flutter app. Type helloworld@g, and you'll notice how the initial h got duplicated.

Conclusions:

β€’ No issue if English is set, only when Swedish is set.
β€’ Works with predictive text OFF.

This is a huge issue in regards of users registering accounts. We've been debugging account issues and finally found out the problem is users having unwanted repeated first letters in their email addresses, and this is the root cause. For bigger production apps with registration processes this can be considered a serious issue. Please escalate and label it accordingly @GaryQian @eseidelGoogle if possible

Update: Devices arrived. Was able to repro the exact bug.

The root of this bug is already labeled customer critical, but I'll add it here too.

I have a workaround that will only help a subset of developers:

If you can control the scope of the content the user is entering, you can restrict that content to only numbers. This bug doesn't seem to be happening on my S8 when the I'm only entering numbers using flutter's numpad keyboard (keyboardType: TextInputType.number).

I have implemented https://github.com/flutter/flutter/pull/43865 as suggested by Samsung, but it seems to be uneffective at resolving this specific issue.

Samsung is claiming to be working on a fix on their side, but I will continue to pursue a solution on the Flutter side as well.

I'm trying Flutter (Channel master, v1.10.16-pre.114, on Mac OS X 10.15.1 19B88, locale en-AR) on my Samsung S9 right now. (Android version 9)

This is the code:

return TextFormField(
      autocorrect: false,
      keyboardType: TextInputType.text,
      decoration: InputDecoration(hintText: 'e-mail'),
    );

I start writing some letters, so far it's ok, then I press @, when I'm going to type the next letter it duplicates the text and add the letter at the end.

Example: I type the word user@ when I type h, the field is updated with user@user@h

Note that:

  • It happens regardless the language you use. (I've used english, spanish and portuguese).
  • It only happens when predictive text is ON.

Is there any news to solve this problem? We are in a complete stupor. Our project is tied to creating text notes and because of this problem we are losing a huge part of the Samsung audience

Developers, respond, help to finally release. This is the basic thing .. text input .. I've been writing to everyone on this issue for half a year now.

I can repro this on the beta channel
[βœ“] Flutter (Channel beta, v1.10.7, on Mac OS X 10.14.6 18G1012, locale en-US)

Using a Samsung Galaxy Note 9
SM N960U1 β€’ android-arm64 β€’ Android 9 (API 28)

Language : English
Default Keyboard : Samsung Keyboard English( US )

using a TextFormField that is initially populated with data, this case 4 characters of Alphabetical characters : "Test"

Steps: ( quotes are not shown in app )
1) Click on the text field so the caret is at the end of the text : "Test"
2) hit the backspace erasing the t: "Tes"
3) enter '6' : "Tes6"
4) enter 'h' : "Tes6Tes6h"

Expected: Final string should be "Tes6h" not "Tes6Tes6h".

This example here will display the issue, using the steps above.( so awesome that's the entire code for an app )

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _userName = 'Test';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Demonstrating Github Issue'),
            Text('https://github.com/flutter/flutter/issues/31512'),
            Text('Issue with repeating text, on Samsung devices'),
            TextFormField(
              decoration: InputDecoration(
                labelText: 'User Name',
              ),
              initialValue: _userName,
              onChanged: (value) {
                print('On Changed ${value.toString()}');
              },
              onSaved: (value) {
                setState(() {
                  _userName = value;
                });
              },
              validator: (value) {
                if (value.trim().isNotEmpty) {
                  return null;
                } else {
                  return 'invalid';
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

I/flutter (23321): On Changed
I/flutter (23321): On Changed Test
I/flutter (23321): On Changed Tes
I/flutter (23321): On Changed Tes6
E/SpannableStringBuilder(23321): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
E/SpannableStringBuilder(23321): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
I/flutter (23321): On Changed Tes6Tes6h

Note: using keyboardType: TextInputType.visiblePassword was a valid workaround for our text inputs.

No word from Samsung about this yet, unfortunately. Flutter may be able to work around the problem similar to how we did fora Samsung Korean input bug in https://github.com/flutter/engine/pull/12432.

I do not know anything about flutter internals but why a native app does not have this problem on samsung devices?

@efreibe Native apps directly use Android's keyboard input API, whereas Flutter has to access this through the IMM (input method manager) and extending BaseInputConnection. Long story short, Samsung's keyboard makes assumptions about the IMM and performs internal caching of contents. Somewhere there is a discrepancy between what was assumed and what Flutter/Samsung are seeing.

No word from Samsung about this yet, unfortunately. Flutter may be able to work around the problem similar to how we did fora Samsung Korean input bug in flutter/engine#12432.

How do we apply this in our project ?? We have Russian language. To use is simply not real ...

Note: using keyboardType: TextInputType.visiblePassword was a valid workaround for our text inputs.

Thanks so much for mentioning this, it works for us as well! Now we can release our app :tada:

Thanks @GaryQian for the clarification.

keyboardType: TextInputType.visiblePassword works because it disables the autocorrect, which is where the bug lies.

No word from Samsung about this yet, unfortunately. Flutter may be able to work around the problem similar to how we did fora Samsung Korean input bug in flutter/engine#12432.

Why don’t you add a detour for the Russian language to the assembly?
This idea will solve the problem at least temporarily ..!

keyboardType: TextInputType.visiblePassword works because it disables the autocorrect, which is where the bug lies.

@GaryQian thanks for pointing this out. Good workaraound.

Note: using keyboardType: TextInputType.visiblePassword was a valid workaround for our text inputs.

TextInputType.visiblePassword can't write Korean😒. (maybe many other asian languages, too)

What is the news on this issue? This is a critical bug, this problem casts doubt on the advisability of using flutter in production.

We consider this a critical bug also. It is high on our priority list but the main engineer who works in this area is currently busy with an even more important project. We hope to look at this before the end of the year or, failing that, very early next year.

In the meantime we are happy to review any fixes that anyone else would like to propose; this is an open source project and everyone is welcome to contribute and join the team!

Working on a workaround/hack for this issue. The duplication happens when the IMM sets the composing text to be the entire contents of the textfield. This is not a problem when typing, as the whole word is set to be the composing region, and setting composing text replaces the entire composing region. However, when the keyboard is hidden, the region is cleared to a collapsed region, so now when the text is set, the entire contents is being appended on to the end, causing duplication.

A clean solution would be to notify the IMM that the composing region has been closed, or otherwise not set the entire composing contents when typing. Exploring how to achieve this.

Gary, thanks for starting working on this.
Just want to note that duplication appears in other cases as well when keyboard is visible.
For example, when typing "Text." with the dot at the end and then start typing without adding a space, duplication appears as well.

screencast 2019-12-16 14-55-00

You'll see text duplicated as new text is typed

Logging efforts show that when starting to type in a box with non-committed contents, Gboard will set the entire contents (or rather, whatever was not yet committed) as the composing region, whereas Samsung is setting a composing region of (0,0).

Since I am unable to modify what/how the IMM calls the API, I may have to implement a hack, maybe by tracking the contents manually on Samsung only. That would definitely not be clean though. Am still looking for a more preferred way of notifying the IMM about the text commit/whatever it needs.

So the behavior of entering punctuation like . and it duplicating seems to be separate from the bug where hiding keyboard and typing causes duplication. Although they are likely related, on a Galaxy S9, only the punctuation bug occurs while on a Galaxy Tab T380, only the keyboard-hide bug occurs.

Is there any progress in solving the problem? We have completed the application and are waiting for a solution to this problem ((
@GaryQian @Hixie

I have come across this issue when entering in an email address with the following:

TextFormField( autocorrect: false, keyboardType: TextInputType.emailAddress, textInputAction: TextInputAction.done, ...),

As soon as I enter anything after the @ symbol, it duplicates the previous text with the new text appended...

This is present on the Samsung Tab A 10.1" (2019)

I stumbled upon the same problem on a Samsung Fold too.

ezgif-6-5b5717cd0b38

How are flutter customers like realtor.com, tencent, alibaba, ebay, capitalone working around this in their production flutter applications? Combined, these companies probably have hundreds of millions of users with samsung phone that would be impacted by this text input bug.

Did they design their own text inputs from the ground up?

How are flutter customers like realtor.com, tencent, alibaba, ebay, capitalone working around this in their production flutter applications? Combined, these companies probably have hundreds of millions of users with samsung phone that would be impacted by this text input bug.

Did they design their own text inputs from the ground up?

No idea what they are doing, but I have all email fields as a stateful widget which use a device info package to check if it's samsung. Add this to email entry text fields:

keyboardType: samsungKeyboard ? TextInputType.visiblePassword : TextInputType.emailAddress,
autoFocus: false,

Autofocus usually needs to be off. If the keyboard goes up before the setState to make samsungKeyboard is true, it won't actually change the keyboard type until it's closed and open again

If they try to type anything with a website, email, or anything with a special character then letters into other plain text fields, the text duplicates and it's horrible

Is there any progress on the issue?

Most of the complaints from our users are related to this issue.
Huge number of our users use Samsung devices and are suffering from just writing the text.
Writing text is the most basic function of the app.
If it doesn't function well, it can adversely affect not only our app, but also the reputation of Flutter.

I know you're working on it, but please resolve this issue as soon as possible.
Number of developers and users are waiting.

@Kiboom Yes, completely understand. Apologize for any blockages/delays/pain this is causing. Trying my best to get this sorted out, but it is one of those problems where all I can do is poke at a black box that is Samsung's keyboard implementation, which is caching certain values differently than every other keyboard. I can only control the way Flutter handles Samsung's invocation of the keyboard API so there is a very limited set of tools/places I can work with. Right now, the key issue is that on Samsung, we are missing an invocation of setComposingRegion, and there is no reliable way that I can see (yet) to obtain that piece of information. It also varies greatly between versions, so different fixes/workarounds only work for a subset of devices.

Just as a note here for reference, the punctuation duplication occurs on a S9 but not on Galaxy Tab.

The punctuation duplication part of this bug is caused by Samsung not resetting their internally cached composing region after calling finishComposingText(), which is a method that commits and resets the composing region. I was able to work around it by manually sending an empty composing region in an overridden finishComposingText() back to the keyboard. https://github.com/flutter/engine/pull/15701 implements this.

Have confirmed text no longer duplicates on punctuation. The change has made it into master channel via https://github.com/flutter/flutter/commit/fbb2f07497868a2b63c23abaa31aed02fc13d057

There is still the second half of the bug where text duplicates when the keyboard is hidden+unhidden+type. This does not pass through the finishComposingText codepath and requires a different workaround.

Are there any news?

Not yet, have been continuing with experimentation, but not much success yet. Will update when I have more information. The remaining portion of this bug is caused by a similar issue with finishing composing region and how Samsung caches that internally. When the keyboard is hidden, the composing region finishes, however, Samsung does not clear their cache, and incorrectly reinstates it when the keyboard is shown again, causing the duplication. The hard part is finding a reliable way to notify/force the keyboard to clear out its cache in a general way that doesn't break other keyboards.

Go, @GaryQian. Go! You can do it!!

Update: The hack I was able to use to fix the "dupe on punctuation" part of the bug does not work with the "keyboard hide-show dupe" part of this bug. I have confirmed I am successfully resetting composing regions on keyboard hide/show with no positive results. It seems this cached value is stored somewhere else, or Samsung has not full implemented receiving composing region data in the IME. Continuing the search...

I believe I have another partial fix that resolves this bug in the vast majority of cases. It seems there is yet a third way the duplication happens, but I was able to use the updateSelection IMM call to trick the keyboard into resetting its cached composing region in https://github.com/flutter/engine/pull/16547.

This fixes the duplication (on my test devices) for almost all cases, but in a few rare instances (exact repro steps yet to be determined), I am still able to duplicate. I will try to land the current state of the hack/fix because this is an important bugfix and most cases are covered by it.

The partial workaround has been landed. https://github.com/flutter/engine/commit/c4c6ef67195bd7b592ede2769702ecb7253e525c Still needs to roll into the framework, but it should hugely improve the duplication behavior. Please try it out (after it rolls into framework).

If anyone can come up with reliable steps to reproduce the remaining duplication edge case, please share! I am able to repro it every once in a while, but am unable to achieve it consistently.

I used S10 plus with android 10
EspaΓ±ol (US) idiom

Scenario

Tap textformfield
Enter a letter
Done
Tap textformfield
Enter a dot (.)
Enter any letter

reproduce today 13/2/2020

The fix above has rolled into master channel as of https://github.com/flutter/flutter/commit/6ecb0521399c3148aaac513921cd51a3e17e56a9 today. Please try it now.

@ccarbajo You probably tried on a version that did not include the fix as it only just rolled into the frtamework, please try it on master channel now :)

Thank you @GaryQian for your efforts. Unfortunately, our issues are not resolved based on our observations.

We created a simple example application with this TextField:

TextField(
  autocorrect: false,
  enableSuggestions: false,
)

Input is still duplicated when typing a letter after @ or ..

In fact, the issue seems to have worsened for us, as now the very first character that is typed is sometimes duplicated as well, which was not the case before.

Duplication of first character seems to be related to hiding + unhiding the keyboard, or changing focus back & forth.

Here is a short video showing both issues.

ezgif-6-abaec488e429

Device is a Galaxy Tab A (2019, 10.1). Tried both with english & german locale.

flutter doctor:

[βœ“] Flutter (Channel master, v1.15.4-pre.83, on Linux, locale en_US.UTF-8)
    β€’ Flutter version 1.15.4-pre.83 at /opt/flutter
    β€’ Framework revision ec9813a500 (8 hours ago), 2020-02-16 19:15:52 -0800
    β€’ Engine revision d60f298d9e
    β€’ Dart version 2.8.0 (build 2.8.0-dev.9.0 edd64e6d5c)


[βœ“] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    β€’ Android SDK at /home/ren/Android/Sdk
    β€’ Android NDK location not configured (optional; useful for native profiling support)
    β€’ Platform android-29, build-tools 29.0.2
    β€’ Java binary at: /home/ren/.local/share/JetBrains/Toolbox/apps/AndroidStudio/ch-0/191.6010548/jre/bin/java
    β€’ Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    β€’ All Android licenses accepted.

[βœ“] Android Studio (version 3.5)
    β€’ Android Studio at /home/ren/.local/share/JetBrains/Toolbox/apps/AndroidStudio/ch-0/191.6010548
    β€’ Flutter plugin version 40.0.2
    β€’ Dart plugin version 191.8423
    β€’ Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)

[βœ“] Connected device (1 available)
    β€’ SM T510 β€’ R52M400PMFN β€’ android-arm β€’ Android 9 (API 28)

This is a real issue. Any news from the front? Building with master of flutter and still experiencing this issue.

@Endebert Thanks for the detailed report!

If anyone else has also not seen improvement on master channel, please share your flutter doctor as well as the device you are seeing the bug on: Exact model, Android version, and Samsung Experience Version.

The bug has seen improvement on the array of my test devices, but I do not (yet) possess a comprehensive samsung device library. If we can narrow down the remaining behavior on a subset of devices, I can purchase the device to ensure it is fixed on them.

@Endebert Thanks for the detailed report!

If anyone else has also not seen improvement, please share your flutter doctor as well as the device you are seeing the bug on: Exact model, Android version, and Samsung Experience Version.

The bug has seen improvement on the array of my test devices, but I do not (yet) possess a comprehensive samsung device library. If we can narrow down the remaining behavior on a subset of devices, I can purchase the device to ensure it is fixed on them.

  • I share the current state of bug reproduction and confirmation as below.
    After applying your update, duplicate input problems still occur, and customer dissatisfaction is escalating.

  • Reproduce this bug

    • run time : 2020-02-11 11:44:36
    • I have been told that duplicate input is coming from a user using the Galaxy s7 and Galaxy s8. To find out, I bought a Galaxy S8 device. After updating the flutter to the latest version and building the app to check the issue, the duplicate input problem did not improve and is still occurring. The duplicate text input problem is a very basic and critical flaw. This should be fixed as soon as possible, so please...
      Cheering and Believing You^^
    • How to reproduce the sentence : After entering a word, lower and raise the soft keyboard. -> After entering a word again, press the space button or wait for a while to change the input status to dormant. -> Afterwards, when you try to enter the next word, the cursor moves to the front and the first word changes to the second word you entered before. After that, when enter any word, a lot of duplicate words start to be entered.
    • Perhaps the Samsung Galaxy S7, S8 and S9 still have duplicate input issues. I don't know about S10 or etc.
  • Development environment information
    Flutter 1.12.13+hotfix.8 β€’ channel stable β€’ https://github.com/flutter/flutter.git
    [βœ“] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    β€’ Android SDK at /Users/xxx/Library/Android/sdk
    β€’ Android NDK location not configured (optional; useful for native profiling support)
    β€’ Platform android-29, build-tools 29.0.2
    β€’ Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    β€’ Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    β€’ All Android licenses accepted.
    [βœ“] Xcode - develop for iOS and macOS (Xcode 11.3.1)
    β€’ Xcode at /Applications/Xcode.app/Contents/Developer
    β€’ Xcode 11.3.1, Build version 11C504
    β€’ CocoaPods version 1.8.4
    [βœ“] Android Studio (version 3.5)
    β€’ Android Studio at /Applications/Android Studio.app/Contents
    β€’ Flutter plugin version 43.0.1
    β€’ Dart plugin version 191.8593
    β€’ Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
    [βœ“] Connected device (1 available)
    β€’ SM G950N β€’ xxxxxxxxxxx β€’ android-arm64 β€’ Android 9 (API 28)

I think you'd better buy a Galaxy S8 real device to fix this bug.
Have a nice day. Thanks.

A few years ago when I developed an app with Firemonkey, I encountered several bugs in text input. The self-drawing control framework is very cool in interface development, but many bugs in text input will make developers and customers crazy. It is recommended that Google focus on solving several bugs in text input first. After all, this is a must-have feature for almost all apps.

@exptk3 You are testing on stable channel, which does not have the fixes. Please try again on master channel (flutter channel master).

I have verified it is fixed on the following test devices I have: S7 S9 S10 Note9 (same generation as s8), as well as on various tablets including Galaxy Tab A 2017 and 2018. I also have access to a bunch of pre-s7 devices that I have not recently tried, but those devices are quite old now and many of them did not repro the issue originally.

I was able to reproduce the punctuation version of this bug on a J6+ that I dug up (SM J610G/DS). The hide keyboard version of this bug does not occur.

@exptk3 You are testing on stable channel, which does not have the fixes. Please try again on master channel (flutter channel master).

I have verified it is fixed on the following test devices I have: S7 S9 S10 Note9 (same generation as s8), as well as on various tablets including Galaxy Tab A 2017 and 2018. I also have access to a bunch of pre-s7 devices that I have not recently tried, but those devices are quite old now and many of them did not repro the issue originally.

Okay.
I just tested it on the master channel. By the way, the duplicate input problem still occurred and there was another problem added that was not present.
It took about 3~15 seconds or more(The time required is different each time) for the keyboard to come up and down to work.
After the keyboard went down and up, the duplicate input problem still occurred.
Even the keyboard that came up after the exit of the app is on the phone home screen.
The current situation is worse than before, so even users of other countries who do not use the Korean keyboard can cause problems.

* Another Bug confirmed
In addition to the above, after applying the master channel's modifications, the enter to go to the next line was also disabled. This will break from the first use of the text field regardless of keyboard up & down and will not go to the next line.

My test device is the Galaxy S8 as mentioned in the article above.
Please check the above


  • This is my TextField (nothing special)
    TextField(
    maxLengthEnforced: true,
    maxLength: 500,
    decoration: InputDecoration(
    labelStyle: TextStyle(fontSize: 15),
    labelText: 'xxxxxx',
    hintStyle: TextStyle(
    fontSize: 13, color: Colors.grey[400]),
    hintText: 'xxxxxx',
    ),
    controller: _xxxxxController,
    keyboardType: TextInputType.multiline,
    maxLines: null,
    onChanged: (val) {xxx },

    )

  • Console message when keyboard up and down

    1. keyboard down
      D/ViewRootImpl@3eb9136MainActivity: MSG_RESIZED: frame=Rect(0, 0 - 1080, 2220) ci=Rect(0, 72 - 0, 144) vi=Rect(0, 72 - 0, 144) or=1
      D/ViewRootImpl@3eb9136MainActivity: Relayout returned: old=[0,0][1080,2220] new=[0,0][1080,2220] result=0x1 surface={valid=true 524530458624} changed=false
  1. keyboard up
    W/IInputConnectionWrapper(21669): getExtractedText on inactive InputConnection
    W/IInputConnectionWrapper(21669): getExtractedText on inactive InputConnection
    W/IInputConnectionWrapper(21669): getExtractedText on inactive InputConnection
    .....
    < ..... same message so many times .....>
    .....
    W/IInputConnectionWrapper(21669): getExtractedText on inactive InputConnection
    W/IInputConnectionWrapper(21669): getExtractedText on inactive InputConnection
    W/IInputConnectionWrapper(21669): getExtractedText on inactive InputConnection

See the console log above.
Thank you.

< Clean Project Test >

The above is the result of testing with my Real World app. I wanted to see if there was any difference in the initial flutter app that I created, so I created a new project and tested it again, but the result is the same as the real app. It was reproduced as it is.

  • In this case, reproduce the duplicate input problem : word input --> hide the keyboard and show keyboard-> type another word-> do not wait for the keyboard focus to disappear naturally, but press the space button(on device soft keyboard) immediately after the word to release the focus. If you do this, duplicate input is better reproduced.
    (this is important test tip)

  • The above test was run on a clean project created like below.

children: [
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
TextField(
maxLengthEnforced: true,
maxLength: 500,
decoration: InputDecoration(
labelStyle: TextStyle(fontSize: 15),
labelText: 'xxxxxx',
hintStyle: TextStyle(
fontSize: 13, color: Colors.grey[400]),
hintText: 'xxxxxx',
),
keyboardType: TextInputType.multiline,
maxLines: null,
onChanged: (val) { },
)
],


  • Console Log (keyboard up and down)
    W/IInputConnectionWrapper(14019): getExtractedText on inactive InputConnection
    W/IInputConnectionWrapper(14019): getExtractedText on inactive InputConnection
    ......
    ..... so many times
    .....
    W/IInputConnectionWrapper(14019): getExtractedText on inactive InputConnection
    W/IInputConnectionWrapper(14019): getExtractedText on inactive InputConnection
    D/ViewRootImpl@82a4301MainActivity: MSG_RESIZED: frame=Rect(0, 0 - 1080, 2220) ci=Rect(0, 72 - 0, 1071) vi=Rect(0, 72 - 0, 1071) or=1
    D/ViewRootImpl@82a4301MainActivity: Relayout returned: old=[0,0][1080,2220] new=[0,0][1080,2220] result=0x1 surface={valid=true 488086081536} changed=false
    D/ViewRootImpl@82a4301MainActivity: ViewPostIme pointer 0
    D/ViewRootImpl@82a4301MainActivity: ViewPostIme pointer 1
    D/InputMethodManager(14019): HSIFW - flag : 0 Pid : 14019
    D/ViewRootImpl@82a4301MainActivity: MSG_RESIZED: frame=Rect(0, 0 - 1080, 2220) ci=Rect(0, 72 - 0, 144) vi=Rect(0, 72 - 0, 144) or=1
    D/ViewRootImpl@82a4301MainActivity: Relayout returned: old=[0,0][1080,2220] new=[0,0][1080,2220] result=0x1 surface={valid=true 488086081536} changed=false

* The problem is summarized below.
Problems occurring when the modified version of the master channel is applied :

  1. Time delay of the keyboard up and down
  2. abnormal display of the keyboard even after the app is closed (on device home screen)
  3. word duplication input
  4. input line can not be changed during keyboard input

I hope this helps you solve various problems.

@GaryQian In case it helps: the Samsung Experience Service version of the device we tested with is 10.6.00.13.

The rest of the information you requested was already included in the flutter doctor I posted, but here it is again:

device: Galaxy Tab A (2019, 10.1)
model: SM-T510
Android version: Android 9 (API 28)

Same problem here on master and a Galaxy Tab A (SM-T510) device.

flutter doctor -v
[βœ“] Flutter (Channel master, v1.15.4-pre.140, on Linux, locale fr_FR.UTF-8)
    β€’ Flutter version 1.15.4-pre.140 at /home/bruno/flutter/flutter
    β€’ Framework revision 1d4667bb38 (il y a 5 heures), 2020-02-24 08:56:02 +0530
    β€’ Engine revision f2f8c342be
    β€’ Dart version 2.8.0 (build 2.8.0-dev.9.0 0f141be8bd)

[!] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    β€’ Android SDK at /home/bruno/Android/Sdk
    β€’ Android NDK location not configured (optional; useful for native profiling support)
    β€’ Platform android-28, build-tools 28.0.3
    β€’ Java binary at: /home/bruno/flutter/android-studio/jre/bin/java
    β€’ Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
    βœ— Android license status unknown.
      Try re-installing or updating your Android SDK Manager.
      See https://developer.android.com/studio/#downloads or visit https://flutter.dev/setup/#android-setup for detailed
      instructions.

[βœ“] Linux toolchain - develop for Linux desktop
    β€’ clang++ 7.0.0
    β€’ GNU Make 4.2.1

[βœ“] Android Studio (version 3.3)
    β€’ Android Studio at /home/bruno/flutter/android-studio
    β€’ Flutter plugin version 34.0.1
    β€’ Dart plugin version 182.5215
    β€’ Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)

[βœ“] VS Code (version 1.42.1)
    β€’ VS Code at /usr/share/code
    β€’ Flutter extension version 3.8.1

[βœ“] Connected device (2 available)
    β€’ SM T510 β€’ R52M40T1T7H β€’ android-arm β€’ Android 9 (API 28)
    β€’ Linux   β€’ Linux       β€’ linux-x64   β€’ Linux

For people looking for a quick workaround : replace Samsung Keyboard app by another Android Keyboard application ;-)

@Endebert @bleroux Since we have two reports of the bug still on SM-T510, I have one ordered, arriving Wednesday.

Can confirm that all versions of this bug still occur on SM-T510 (Galaxy Tab A 2019 10.1")

Update: Interestingly, the devices that are still reproing some variant of this bug are each doing something strange differently.

For example, on SM-T510, the keyboard is sending a finishComposingText call immediately after the first character typed into the field. This is causing it experience the initial character duplication. None of the other samsung keyboards (or non-samsung keyboards) does this. The SMT510 keyboard also seems to completely ignore calls to updateSelection and updateCursorAnchorInfo, almost as if those methods were just not implemented in that version. It seems to totally dependent on its internal tracking of this information. I am able to send any gibberish data through those calls with zero impact on the the results. This makes my workarounds useless on this device.

The duplication is also inconsistent on the J6+.

@GaryQian Wow this seems like a complex issue! I always imagined that someone at Google on such a high profile project such as Flutter would be able to contact the Android and Samsung teams directly to get help with something like this. Not the case?

Is this even allowed ? Unimplememted core functions ?? I cant think that flutter is the only one affected by this , right ??
& can someone explain how the native android text field is working fine ?

Why does flutter even use the native keyboard?! 😏

@tedhenry100 We have been in contact with Samsung, however, this is one of those things where even if they fixed it on their end, we would still have to fix it here as it is unlikely all the keyboards in the wild can be updated.

Since the original filing of this issue, the state of the bug has evolved. The severity has been greatly reduced for most devices, and new behaviors have been uncovered, evolving it towards a different set of issues. Since this can be difficult (and laggy) to follow in this thread of hundreds of comments, I will be moving further discussion to a new issue https://github.com/flutter/flutter/issues/51893 where we can focus on the current state of the issue.

Please continue to contribute/report/comment on https://github.com/flutter/flutter/issues/51893 and reference comments in this thread as appropriate. Thanks!

From the new thread:

I have landed flutter/engine#17426 which seems to fix many of the bugs on my test devices. It would be great if others could confirm that this also fixes bugs for them.

Please try the change on master channel!

@GaryQian I've been testing this keyboard issue and I found a duplicate issue with the latest beta which https://github.com/flutter/engine/pull/17391 is applied.
For some reason the letter '@' causes this duplicates in english as well.

Please do testing on master channel, I believe that bug has already been addressed in the other continuation thread via the getExtractedText() fix.

Beta channel is often times over a month old, and many flutter bugs are fixed/updated on a daily basis.

In particular, the getExtractedText() fix was only landed this week.

@GaryQian I'm using the latest beta 1.17.dev.3.1. Is there any other updates regarding this other than flutter/engine#17391? I will let you know with the latest master commit.

flutter/engine#17426 should resolve the duplication.

@GaryQian I thought #17391 was the latest commit and you are right this issue doesn't appear with the latest master. Sorry for the confusion. I really appreciate your help and thank you very much for your hard work to fix this.

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dancamdev picture dancamdev  Β·  122Comments

eseidelGoogle picture eseidelGoogle  Β·  171Comments

jeroen-meijer picture jeroen-meijer  Β·  157Comments

cbazza picture cbazza  Β·  238Comments

39499740 picture 39499740  Β·  136Comments