15

I have a problem with soft keyboard backspace in Android (4.2).

I have a custom editor in a WebView (CodeMirror), which uses an empty <textarea> internally. It seems that backspace is not sent by an Android system unless it believes there is some text in the <textarea>.

I have overridden WebView onCreateInputConnection in an attempt to dumb down soft input:

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
    Log.d("CustomWebView", "onCreateInputConnection(...)");
    BaseInputConnection connection = new BaseInputConnection(this, false);
    outAttrs.inputType = InputType.TYPE_NULL;
    outAttrs.imeOptions = EditorInfo.IME_ACTION_NONE;
    outAttrs.initialSelStart = -1;
    outAttrs.initialSelEnd = -1;

    return connection;
}

However, this does not work, and even onKeyUp is not called for backspace.

How do I force soft keyboard to always send backspace?

Andrey Shchekin
  • 21,101
  • 19
  • 94
  • 162

2 Answers2

34

Ok, finally figured this out.

In Android 4.2 (maybe in earlier versions as well) the backspace is not sent as a sendKeyEvent(..., KeyEvent.KEYCODE_DEL) by the standard soft keyboard. Instead, it is sent as deleteSurroundingText(1, 0).

So the solution in my case is to make a custom InputConnection with the following:

@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {       
    // magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
    if (beforeLength == 1 && afterLength == 0) {
        // backspace
        return super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
            && super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
    }

    return super.deleteSurroundingText(beforeLength, afterLength);
}

Note: Please let me know if I am doing something stupid here, as it is my 3rd day writing for Android.

Andrey Shchekin
  • 21,101
  • 19
  • 94
  • 162
  • 1
    Hey, I'm also running into this issue...except I'm using Phonegap, so I don't really have much low-level access to the java source code, as it's all compiled. I only have access to the onCreate method, everything else is obfuscated/compiled. Any suggestions? – Nisk May 10 '13 at 21:44
  • Sorry, I have never user PhoneGap, so I can't answer your question — but try asking it as a separate question instead and there should be people familiar with it. – Andrey Shchekin May 11 '13 at 01:24
  • Thanks anyhow, I have posted the question, in case you want to keep an eye on it: http://stackoverflow.com/questions/16499178/cant-get-backspace-to-work-in-codemirror-under-phonegap-on-android-4-x – Nisk May 11 '13 at 16:12
  • Nice find. This was driving me nuts. – André Restivo Jun 09 '13 at 23:35
  • Very nice find. Thanks mate. – Sean Glover Sep 12 '13 at 23:05
  • FYI, here is the Issue report for this bug, which has still not been assigned: https://code.google.com/p/android/issues/detail?id=42904 – Carl Nov 14 '13 at 13:14
  • It seems like this method has stopped working in Android 4.4 KitKat (at least on my Nexus 5). Has anyone else noticed this? I have been unable to find a workaround so far... – pqvst Dec 04 '13 at 11:20
  • Yes, it fails to work for me on 4.3, actually (on Nexus7 2012). Not in a WebView, but that's probably irrelevant. FYI, this problem disappears when I use the third-party SwiftKey soft keyboard. So I'm pretty sure it is a default soft keyboard problem. And it also is not present when I set targetSdkLevel back to API level 15 I believe. So perhaps the default soft keyboard is part of the SDK and not part of the Android installation? Or else, the keyboard that gets selected from the installation depends on the API level. Anyway, I'm going to try targeting a higher level - I'm at 17 now. – Carl Dec 08 '13 at 13:49
  • I have overriden a webview and the custom webview returns customInputConnection from onCreateInputConnection. Is this the right approach? because afther the change, i can't activate the keyboard in my webview. – eugene Dec 10 '14 at 05:23
  • @pbergqvis: not able to make it work either.. on 4.4.2 – eugene Dec 12 '14 at 11:08
  • Surprisingly good workaround for quite a sophisticated challenge - excellent work for someone on 3rd day of Android development. – Melllvar Jan 01 '15 at 07:30
  • This worked great until I switched to a different keyboard and tried to add an emoticon. I switched to `Fleksy` and tried to add an emoticon. It works on the normal webview but not here. Did anyone else faced the issue on switching keyboard to something other than google keyboard? – pratZ Jul 20 '15 at 10:44
  • After hours of trying to find the solution, this worked flawlessly, thanks mate! – Sleeper9 Mar 22 '16 at 17:54
2

this code will be better, it work with more keyboard :D

@Override
  public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
      outAttrs.actionLabel = null;
      outAttrs.inputType = InputType.TYPE_NULL;
      final InputConnection con = new BaseInputConnection(this,false);
      InputConnectionWrapper public_con = new InputConnectionWrapper(
              super.onCreateInputConnection(outAttrs), true) {
          @Override
          public boolean deleteSurroundingText(int beforeLength, int afterLength) {
              if (beforeLength == 1 && afterLength == 0) {
                  return this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
                          && this.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
              }
              return super.deleteSurroundingText(beforeLength, afterLength);
          }

          @Override
          public boolean sendKeyEvent(KeyEvent event) {
              if(event.getKeyCode() == KeyEvent.KEYCODE_DEL){
                  return con.sendKeyEvent(event);
              }else {
                  return super.sendKeyEvent(event);
              }
          }
      };
      try {
          return public_con ;
      }catch (Exception e){
          return super.onCreateInputConnection(outAttrs) ;
      }
  }
Vui Dang
  • 148
  • 9